Merge branch 'deployment' of pedrosaclout/TacticalApp into master
commit
502c82833d
@ -1 +1,8 @@
|
||||
env/
|
||||
env/*
|
||||
venv/
|
||||
venv/*
|
||||
.idea/
|
||||
*.pyc
|
||||
__pycache__/
|
||||
__pycache__/*
|
@ -0,0 +1,75 @@
|
||||
# Run
|
||||
|
||||
## in Development
|
||||
`export FLASK_APP=run.py`
|
||||
`export FLASK_ENV=development`
|
||||
`flask run`
|
||||
|
||||
**Using gunicorn:**
|
||||
|
||||
`gunicorn -w 4 -b 127.0.0.1:5000 app:app`
|
||||
* `-w` workers
|
||||
* `-b` bind to address / unix socker
|
||||
|
||||
**And gunicorn with using unix sock:** (this how it should run in production)
|
||||
`gunicorn --workers 4 --bind unix:app.sock -m 007 app:app `
|
||||
|
||||
## in Production with gunicorn and unix sockets
|
||||
Based on https://medium.com/faun/deploy-flask-app-with-nginx-using-gunicorn-7fda4f50066a
|
||||
|
||||
### systemd service file
|
||||
|
||||
Add to /etc/systemd/system/watermarks.service
|
||||
|
||||
```
|
||||
[Unit]
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=psc
|
||||
Group=www-data
|
||||
WorkingDirectory=/var/www/TacticalApp
|
||||
Environment="PATH=/var/www/TacticalApp/venv/bin"
|
||||
ExecStart=/var/www/TacticalApp/venv/bin/gunicorn --workers 4 --bind unix:app.sock -m 007 app:app
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
## enable & start service file
|
||||
`systemctl enable watermarks.service`
|
||||
|
||||
`systemctl start watermarks.service`
|
||||
|
||||
It is also a good idea to check the status of the service
|
||||
`systemctl status watermarks.service`
|
||||
|
||||
## Nginx config
|
||||
|
||||
```
|
||||
location / {
|
||||
include proxy_params;
|
||||
# it will pass the requests to the socket
|
||||
proxy_pass http://unix:/var/www/TacticalApp/app.sock;
|
||||
# @andre: unsure whether we need a proxy_redirect as well
|
||||
# if so, it might be somthing like
|
||||
# http://unix:/var/www/TacticalApp/app.sock $scheme://$host:80/;
|
||||
}
|
||||
```
|
||||
|
||||
## debug.
|
||||
|
||||
It might be helpful to enable gunicorn logging, while in development, to check what is going on,
|
||||
by replacing in watermarks.service, the `ExecStart=` value with:
|
||||
|
||||
`ExecStart=/var/www/TacticalApp/venv/bin/gunicorn --log-level debug --error-logfile /var/www/TacticalApp/app.log --workers 4 --bind unix:app.sock -m 007 app:app`
|
||||
|
||||
And reloading the services
|
||||
`systemctl daemon-reload`
|
||||
|
||||
`systemctl restart watermarks.service`
|
||||
|
||||
and the start following app.log:
|
||||
`tail -f /var/www/TacticalApp/app.log`
|
||||
|
||||
But in the long run logging should be disabled
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,21 +1,4 @@
|
||||
alembic
|
||||
click
|
||||
console-log
|
||||
dataset
|
||||
Flask
|
||||
Flask-SQLAlchemy
|
||||
gevent
|
||||
gevent-websocket
|
||||
greenlet
|
||||
gunicorn
|
||||
itsdangerous
|
||||
Jinja2
|
||||
Mako
|
||||
MarkupSafe
|
||||
python-dateutil
|
||||
python-editor
|
||||
setuptools
|
||||
six
|
||||
SQLAlchemy
|
||||
Werkzeug
|
||||
wsgigzip
|
||||
Flask==1.0.2
|
||||
gunicorn==20.0.4
|
||||
Jinja2==2.11.1
|
||||
dataset==1.3.1
|
||||
|
@ -1,76 +0,0 @@
|
||||
# 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="/var/www/TacticalApp/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
|
@ -1,37 +0,0 @@
|
||||
# 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 "/var/www/TacticalApp/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
|
@ -1,75 +0,0 @@
|
||||
# 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 "/var/www/TacticalApp/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
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from alembic.config import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/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())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/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())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from flask.cli import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from gunicorn.app.wsgiapp import run
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(run())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/venv/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from mako.cmd import cmdline
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(cmdline())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/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())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/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())
|
@ -1,10 +0,0 @@
|
||||
#!/var/www/TacticalApp/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())
|
@ -1 +0,0 @@
|
||||
python3
|
@ -1 +0,0 @@
|
||||
/usr/bin/python3
|
@ -1,157 +0,0 @@
|
||||
/* vim:set noet ts=8 sw=8 : */
|
||||
|
||||
/* Greenlet object interface */
|
||||
|
||||
#ifndef Py_GREENLETOBJECT_H
|
||||
#define Py_GREENLETOBJECT_H
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GREENLET_VERSION "0.4.15"
|
||||
|
||||
#if PY_VERSION_HEX >= 0x030700A3
|
||||
# define GREENLET_USE_EXC_INFO
|
||||
#endif
|
||||
|
||||
typedef struct _greenlet {
|
||||
PyObject_HEAD
|
||||
char* stack_start;
|
||||
char* stack_stop;
|
||||
char* stack_copy;
|
||||
intptr_t stack_saved;
|
||||
struct _greenlet* stack_prev;
|
||||
struct _greenlet* parent;
|
||||
PyObject* run_info;
|
||||
struct _frame* top_frame;
|
||||
int recursion_depth;
|
||||
PyObject* weakreflist;
|
||||
#ifdef GREENLET_USE_EXC_INFO
|
||||
_PyErr_StackItem* exc_info;
|
||||
_PyErr_StackItem exc_state;
|
||||
#else
|
||||
PyObject* exc_type;
|
||||
PyObject* exc_value;
|
||||
PyObject* exc_traceback;
|
||||
#endif
|
||||
PyObject* dict;
|
||||
} PyGreenlet;
|
||||
|
||||
#define PyGreenlet_Check(op) PyObject_TypeCheck(op, &PyGreenlet_Type)
|
||||
#define PyGreenlet_MAIN(op) (((PyGreenlet*)(op))->stack_stop == (char*) -1)
|
||||
#define PyGreenlet_STARTED(op) (((PyGreenlet*)(op))->stack_stop != NULL)
|
||||
#define PyGreenlet_ACTIVE(op) (((PyGreenlet*)(op))->stack_start != NULL)
|
||||
#define PyGreenlet_GET_PARENT(op) (((PyGreenlet*)(op))->parent)
|
||||
|
||||
#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 1) || PY_MAJOR_VERSION > 3
|
||||
#define GREENLET_USE_PYCAPSULE
|
||||
#endif
|
||||
|
||||
/* C API functions */
|
||||
|
||||
/* Total number of symbols that are exported */
|
||||
#define PyGreenlet_API_pointers 8
|
||||
|
||||
#define PyGreenlet_Type_NUM 0
|
||||
#define PyExc_GreenletError_NUM 1
|
||||
#define PyExc_GreenletExit_NUM 2
|
||||
|
||||
#define PyGreenlet_New_NUM 3
|
||||
#define PyGreenlet_GetCurrent_NUM 4
|
||||
#define PyGreenlet_Throw_NUM 5
|
||||
#define PyGreenlet_Switch_NUM 6
|
||||
#define PyGreenlet_SetParent_NUM 7
|
||||
|
||||
#ifndef GREENLET_MODULE
|
||||
/* This section is used by modules that uses the greenlet C API */
|
||||
static void **_PyGreenlet_API = NULL;
|
||||
|
||||
#define PyGreenlet_Type (*(PyTypeObject *) _PyGreenlet_API[PyGreenlet_Type_NUM])
|
||||
|
||||
#define PyExc_GreenletError \
|
||||
((PyObject *) _PyGreenlet_API[PyExc_GreenletError_NUM])
|
||||
|
||||
#define PyExc_GreenletExit \
|
||||
((PyObject *) _PyGreenlet_API[PyExc_GreenletExit_NUM])
|
||||
|
||||
/*
|
||||
* PyGreenlet_New(PyObject *args)
|
||||
*
|
||||
* greenlet.greenlet(run, parent=None)
|
||||
*/
|
||||
#define PyGreenlet_New \
|
||||
(* (PyGreenlet * (*)(PyObject *run, PyGreenlet *parent)) \
|
||||
_PyGreenlet_API[PyGreenlet_New_NUM])
|
||||
|
||||
/*
|
||||
* PyGreenlet_GetCurrent(void)
|
||||
*
|
||||
* greenlet.getcurrent()
|
||||
*/
|
||||
#define PyGreenlet_GetCurrent \
|
||||
(* (PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
|
||||
|
||||
/*
|
||||
* PyGreenlet_Throw(
|
||||
* PyGreenlet *greenlet,
|
||||
* PyObject *typ,
|
||||
* PyObject *val,
|
||||
* PyObject *tb)
|
||||
*
|
||||
* g.throw(...)
|
||||
*/
|
||||
#define PyGreenlet_Throw \
|
||||
(* (PyObject * (*) \
|
||||
(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)) \
|
||||
_PyGreenlet_API[PyGreenlet_Throw_NUM])
|
||||
|
||||
/*
|
||||
* PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
|
||||
*
|
||||
* g.switch(*args, **kwargs)
|
||||
*/
|
||||
#define PyGreenlet_Switch \
|
||||
(* (PyObject * (*)(PyGreenlet *greenlet, PyObject *args, PyObject *kwargs)) \
|
||||
_PyGreenlet_API[PyGreenlet_Switch_NUM])
|
||||
|
||||
/*
|
||||
* PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
|
||||
*
|
||||
* g.parent = new_parent
|
||||
*/
|
||||
#define PyGreenlet_SetParent \
|
||||
(* (int (*)(PyGreenlet *greenlet, PyGreenlet *nparent)) \
|
||||
_PyGreenlet_API[PyGreenlet_SetParent_NUM])
|
||||
|
||||
/* Macro that imports greenlet and initializes C API */
|
||||
#ifdef GREENLET_USE_PYCAPSULE
|
||||
#define PyGreenlet_Import() \
|
||||
{ \
|
||||
_PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
|
||||
}
|
||||
#else
|
||||
#define PyGreenlet_Import() \
|
||||
{ \
|
||||
PyObject *module = PyImport_ImportModule("greenlet"); \
|
||||
if (module != NULL) { \
|
||||
PyObject *c_api_object = PyObject_GetAttrString( \
|
||||
module, "_C_API"); \
|
||||
if (c_api_object != NULL && PyCObject_Check(c_api_object)) { \
|
||||
_PyGreenlet_API = \
|
||||
(void **) PyCObject_AsVoidPtr(c_api_object); \
|
||||
Py_DECREF(c_api_object); \
|
||||
} \
|
||||
Py_DECREF(module); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GREENLET_MODULE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_GREENLETOBJECT_H */
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,28 +0,0 @@
|
||||
Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,134 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Flask
|
||||
Version: 1.1.1
|
||||
Summary: A simple framework for building complex web applications.
|
||||
Home-page: https://palletsprojects.com/p/flask/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: Pallets
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Documentation, https://flask.palletsprojects.com/
|
||||
Project-URL: Code, https://github.com/pallets/flask
|
||||
Project-URL: Issue tracker, https://github.com/pallets/flask/issues
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Framework :: Flask
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
||||
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
||||
Requires-Dist: Werkzeug (>=0.15)
|
||||
Requires-Dist: Jinja2 (>=2.10.1)
|
||||
Requires-Dist: itsdangerous (>=0.24)
|
||||
Requires-Dist: click (>=5.1)
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pytest ; extra == 'dev'
|
||||
Requires-Dist: coverage ; extra == 'dev'
|
||||
Requires-Dist: tox ; extra == 'dev'
|
||||
Requires-Dist: sphinx ; extra == 'dev'
|
||||
Requires-Dist: pallets-sphinx-themes ; extra == 'dev'
|
||||
Requires-Dist: sphinxcontrib-log-cabinet ; extra == 'dev'
|
||||
Requires-Dist: sphinx-issues ; extra == 'dev'
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: pallets-sphinx-themes ; extra == 'docs'
|
||||
Requires-Dist: sphinxcontrib-log-cabinet ; extra == 'docs'
|
||||
Requires-Dist: sphinx-issues ; extra == 'docs'
|
||||
Provides-Extra: dotenv
|
||||
Requires-Dist: python-dotenv ; extra == 'dotenv'
|
||||
|
||||
Flask
|
||||
=====
|
||||
|
||||
Flask is a lightweight `WSGI`_ web application framework. It is designed
|
||||
to make getting started quick and easy, with the ability to scale up to
|
||||
complex applications. It began as a simple wrapper around `Werkzeug`_
|
||||
and `Jinja`_ and has become one of the most popular Python web
|
||||
application frameworks.
|
||||
|
||||
Flask offers suggestions, but doesn't enforce any dependencies or
|
||||
project layout. It is up to the developer to choose the tools and
|
||||
libraries they want to use. There are many extensions provided by the
|
||||
community that make adding new functionality easy.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
pip install -U Flask
|
||||
|
||||
|
||||
A Simple Example
|
||||
----------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def hello():
|
||||
return "Hello, World!"
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ env FLASK_APP=hello.py flask run
|
||||
* Serving Flask app "hello"
|
||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
For guidance on setting up a development environment and how to make a
|
||||
contribution to Flask, see the `contributing guidelines`_.
|
||||
|
||||
.. _contributing guidelines: https://github.com/pallets/flask/blob/master/CONTRIBUTING.rst
|
||||
|
||||
|
||||
Donate
|
||||
------
|
||||
|
||||
The Pallets organization develops and supports Flask and the libraries
|
||||
it uses. In order to grow the community of contributors and users, and
|
||||
allow the maintainers to devote more time to the projects, `please
|
||||
donate today`_.
|
||||
|
||||
.. _please donate today: https://psfmember.org/civicrm/contribute/transact?reset=1&id=20
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
* Website: https://palletsprojects.com/p/flask/
|
||||
* Documentation: https://flask.palletsprojects.com/
|
||||
* Releases: https://pypi.org/project/Flask/
|
||||
* Code: https://github.com/pallets/flask
|
||||
* Issue tracker: https://github.com/pallets/flask/issues
|
||||
* Test status: https://dev.azure.com/pallets/flask/_build
|
||||
* Official chat: https://discord.gg/t6rrQZH
|
||||
|
||||
.. _WSGI: https://wsgi.readthedocs.io
|
||||
.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/
|
||||
.. _Jinja: https://www.palletsprojects.com/p/jinja/
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
../../../bin/flask,sha256=s-6d4F3VC8_p4RMKgO4CDN_Wbz-3ik6F2Qv69FO-mCU,232
|
||||
Flask-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Flask-1.1.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||
Flask-1.1.1.dist-info/METADATA,sha256=Ht4R6TpTKOaXOmmQHhEF3A0Obpzde2Ai0kzNdu6-VWQ,4400
|
||||
Flask-1.1.1.dist-info/RECORD,,
|
||||
Flask-1.1.1.dist-info/WHEEL,sha256=h_aVn5OB2IERUjMbi2pucmR_zzWJtk303YXvhh60NJ8,110
|
||||
Flask-1.1.1.dist-info/entry_points.txt,sha256=gBLA1aKg0OYR8AhbAfg8lnburHtKcgJLDU52BBctN0k,42
|
||||
Flask-1.1.1.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6
|
||||
flask/__init__.py,sha256=qaBW4gy9Xxmdc3ygYO0_H214H1VpF7fq8xRR4XbqRjE,1894
|
||||
flask/__main__.py,sha256=fjVtt3QTANXlpJCOv3Ha7d5H-76MwzSIOab7SFD9TEk,254
|
||||
flask/__pycache__/__init__.cpython-37.pyc,,
|
||||
flask/__pycache__/__main__.cpython-37.pyc,,
|
||||
flask/__pycache__/_compat.cpython-37.pyc,,
|
||||
flask/__pycache__/app.cpython-37.pyc,,
|
||||
flask/__pycache__/blueprints.cpython-37.pyc,,
|
||||
flask/__pycache__/cli.cpython-37.pyc,,
|
||||
flask/__pycache__/config.cpython-37.pyc,,
|
||||
flask/__pycache__/ctx.cpython-37.pyc,,
|
||||
flask/__pycache__/debughelpers.cpython-37.pyc,,
|
||||
flask/__pycache__/globals.cpython-37.pyc,,
|
||||
flask/__pycache__/helpers.cpython-37.pyc,,
|
||||
flask/__pycache__/logging.cpython-37.pyc,,
|
||||
flask/__pycache__/sessions.cpython-37.pyc,,
|
||||
flask/__pycache__/signals.cpython-37.pyc,,
|
||||
flask/__pycache__/templating.cpython-37.pyc,,
|
||||
flask/__pycache__/testing.cpython-37.pyc,,
|
||||
flask/__pycache__/views.cpython-37.pyc,,
|
||||
flask/__pycache__/wrappers.cpython-37.pyc,,
|
||||
flask/_compat.py,sha256=8KPT54Iig96TuLipdogLRHNYToIcg-xPhnSV5VRERnw,4099
|
||||
flask/app.py,sha256=gLZInxueeQ9dkBo1wrntZ-bZqiDT4rYxy_AQ1xraFDc,98066
|
||||
flask/blueprints.py,sha256=vkdm8NusGsfZUeIfPdCluj733QFmiQcT4Sk1tuZLUjw,21400
|
||||
flask/cli.py,sha256=_WhPG1bggNdrP0QO95Vex6VJpDqTsVK0z54Y5poljKU,30933
|
||||
flask/config.py,sha256=3dejvQRYfNHw_V7dCLMxU8UNFpL34xIKemN7gHZIZ8Y,10052
|
||||
flask/ctx.py,sha256=cks-omGedkxawHFo6bKIrdOHsJCAgg1i_NWw_htxb5U,16724
|
||||
flask/debughelpers.py,sha256=-whvPKuAoU8AZ9c1z_INuOeBgfYDqE1J2xNBsoriugU,6475
|
||||
flask/globals.py,sha256=OgcHb6_NCyX6-TldciOdKcyj4PNfyQwClxdMhvov6aA,1637
|
||||
flask/helpers.py,sha256=x2Pa85R5dV6uA5f5423JTb6x4u6ZaMGf8sfosUZ76dQ,43004
|
||||
flask/json/__init__.py,sha256=6nITbZYiYOPB8Qfi1-dvsblwn01KRz8VOsMBIZyaYek,11988
|
||||
flask/json/__pycache__/__init__.cpython-37.pyc,,
|
||||
flask/json/__pycache__/tag.cpython-37.pyc,,
|
||||
flask/json/tag.py,sha256=vq9GOllg_0kTWKuVFrwmkeOQzR-jdBD23x-89JyCCQI,8306
|
||||
flask/logging.py,sha256=WcY5UkqTysGfmosyygSlXyZYGwOp3y-VsE6ehoJ48dk,3250
|
||||
flask/sessions.py,sha256=G0KsEkr_i1LG_wOINwFSOW3ts7Xbv4bNgEZKc7TRloc,14360
|
||||
flask/signals.py,sha256=yYLOed2x8WnQ7pirGalQYfpYpCILJ0LJhmNSrnWvjqw,2212
|
||||
flask/templating.py,sha256=F8E_IZXn9BGsjMzUJ5N_ACMyZdiFBp_SSEaUunvfZ7g,4939
|
||||
flask/testing.py,sha256=b0QaEejx0UcXqfSFP43k5W57bTVeDyrNK3uPD8JUpCk,10146
|
||||
flask/views.py,sha256=eeWnadLAj0QdQPLtjKipDetRZyG62CT2y7fNOFDJz0g,5802
|
||||
flask/wrappers.py,sha256=kgsvtZuMM6RQaDqhRbc5Pcj9vqTnaERl2pmXcdGL7LU,4736
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.4)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1,3 +0,0 @@
|
||||
[console_scripts]
|
||||
flask = flask.cli:main
|
||||
|
@ -1 +0,0 @@
|
||||
flask
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,28 +0,0 @@
|
||||
Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,94 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Flask-SQLAlchemy
|
||||
Version: 2.4.1
|
||||
Summary: Adds SQLAlchemy support to your Flask application.
|
||||
Home-page: https://github.com/pallets/flask-sqlalchemy
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: Pallets
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Documentation, https://flask-sqlalchemy.palletsprojects.com/
|
||||
Project-URL: Code, https://github.com/pallets/flask-sqlalchemy
|
||||
Project-URL: Issue tracker, https://github.com/pallets/flask-sqlalchemy/issues
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*
|
||||
Requires-Dist: Flask (>=0.10)
|
||||
Requires-Dist: SQLAlchemy (>=0.8.0)
|
||||
|
||||
Flask-SQLAlchemy
|
||||
================
|
||||
|
||||
Flask-SQLAlchemy is an extension for `Flask`_ that adds support for
|
||||
`SQLAlchemy`_ to your application. It aims to simplify using SQLAlchemy
|
||||
with Flask by providing useful defaults and extra helpers that make it
|
||||
easier to accomplish common tasks.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip install -U Flask-SQLAlchemy
|
||||
|
||||
|
||||
A Simple Example
|
||||
----------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite"
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String, unique=True, nullable=False)
|
||||
email = db.Column(db.String, unique=True, nullable=False)
|
||||
|
||||
|
||||
db.session.add(User(name="Flask", email="example@example.com"))
|
||||
db.session.commit()
|
||||
|
||||
users = User.query.all()
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- Documentation: https://flask-sqlalchemy.palletsprojects.com/
|
||||
- Releases: https://pypi.org/project/Flask-SQLAlchemy/
|
||||
- Code: https://github.com/pallets/flask-sqlalchemy
|
||||
- Issue tracker: https://github.com/pallets/flask-sqlalchemy/issues
|
||||
- Test status: https://travis-ci.org/pallets/flask-sqlalchemy
|
||||
- Test coverage: https://codecov.io/gh/pallets/flask-sqlalchemy
|
||||
|
||||
.. _Flask: https://palletsprojects.com/p/flask/
|
||||
.. _SQLAlchemy: https://www.sqlalchemy.org
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/METADATA,sha256=SO2Yy86hBglL9QIQxNdZqKPPBaS-3LrvuYbMG6wHuKI,3128
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/RECORD,,
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
|
||||
Flask_SQLAlchemy-2.4.1.dist-info/top_level.txt,sha256=w2K4fNNoTh4HItoFfz2FRQShSeLcvHYrzU_sZov21QU,17
|
||||
flask_sqlalchemy/__init__.py,sha256=qaMQKMcAVz3et6XhUqOyjzpn8V7NUghH5hHSZvyEJUw,39027
|
||||
flask_sqlalchemy/__pycache__/__init__.cpython-37.pyc,,
|
||||
flask_sqlalchemy/__pycache__/_compat.cpython-37.pyc,,
|
||||
flask_sqlalchemy/__pycache__/model.cpython-37.pyc,,
|
||||
flask_sqlalchemy/__pycache__/utils.cpython-37.pyc,,
|
||||
flask_sqlalchemy/_compat.py,sha256=yua0ZSgVWwi56QpEgwaPInzkNQ9PFb7YQdvEk3dImXo,821
|
||||
flask_sqlalchemy/model.py,sha256=9jBoPU1k0c4nqz2-KyYnfoE55n-1G8Zxfo2Z-ZHV0v4,4992
|
||||
flask_sqlalchemy/utils.py,sha256=4eHqAbYElnJ3NbSAHhuINckoAHDABoxjleMJD0iKgyg,1390
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1 +0,0 @@
|
||||
flask_sqlalchemy
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,28 +0,0 @@
|
||||
Copyright 2007 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,106 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Jinja2
|
||||
Version: 2.11.1
|
||||
Summary: A very fast and expressive template engine.
|
||||
Home-page: https://palletsprojects.com/p/jinja/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: Pallets
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Documentation, https://jinja.palletsprojects.com/
|
||||
Project-URL: Code, https://github.com/pallets/jinja
|
||||
Project-URL: Issue tracker, https://github.com/pallets/jinja/issues
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
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
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
||||
Description-Content-Type: text/x-rst
|
||||
Requires-Dist: MarkupSafe (>=0.23)
|
||||
Provides-Extra: i18n
|
||||
Requires-Dist: Babel (>=0.8) ; extra == 'i18n'
|
||||
|
||||
Jinja
|
||||
=====
|
||||
|
||||
Jinja is a fast, expressive, extensible templating engine. Special
|
||||
placeholders in the template allow writing code similar to Python
|
||||
syntax. Then the template is passed data to render the final document.
|
||||
|
||||
It includes:
|
||||
|
||||
- Template inheritance and inclusion.
|
||||
- Define and import macros within templates.
|
||||
- HTML templates can use autoescaping to prevent XSS from untrusted
|
||||
user input.
|
||||
- A sandboxed environment can safely render untrusted templates.
|
||||
- AsyncIO support for generating templates and calling async
|
||||
functions.
|
||||
- I18N support with Babel.
|
||||
- Templates are compiled to optimized Python code just-in-time and
|
||||
cached, or can be compiled ahead-of-time.
|
||||
- Exceptions point to the correct line in templates to make debugging
|
||||
easier.
|
||||
- Extensible filters, tests, functions, and even syntax.
|
||||
|
||||
Jinja's philosophy is that while application logic belongs in Python if
|
||||
possible, it shouldn't make the template designer's job difficult by
|
||||
restricting functionality too much.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip install -U Jinja2
|
||||
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
||||
In A Nutshell
|
||||
-------------
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Members{% endblock %}
|
||||
{% block content %}
|
||||
<ul>
|
||||
{% for user in users %}
|
||||
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- Website: https://palletsprojects.com/p/jinja/
|
||||
- Documentation: https://jinja.palletsprojects.com/
|
||||
- Releases: https://pypi.org/project/Jinja2/
|
||||
- Code: https://github.com/pallets/jinja
|
||||
- Issue tracker: https://github.com/pallets/jinja/issues
|
||||
- Test status: https://dev.azure.com/pallets/jinja/_build
|
||||
- Official chat: https://discord.gg/t6rrQZH
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
Jinja2-2.11.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Jinja2-2.11.1.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475
|
||||
Jinja2-2.11.1.dist-info/METADATA,sha256=7e9_tz7RirTbxIeiHTSq3e5g6ddCjoym3o5vdlRLuxU,3535
|
||||
Jinja2-2.11.1.dist-info/RECORD,,
|
||||
Jinja2-2.11.1.dist-info/WHEEL,sha256=hq9T7ntHzQqUTLUmJ2UVhPL-W4tJi3Yb2Lh5lMfs2mk,110
|
||||
Jinja2-2.11.1.dist-info/entry_points.txt,sha256=Qy_DkVo6Xj_zzOtmErrATe8lHZhOqdjpt3e4JJAGyi8,61
|
||||
Jinja2-2.11.1.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7
|
||||
jinja2/__init__.py,sha256=Nq1rzGErXYjIQnqc1pDCJht5LmInBRIZkeL2qkrYEyI,1549
|
||||
jinja2/__pycache__/__init__.cpython-37.pyc,,
|
||||
jinja2/__pycache__/_compat.cpython-37.pyc,,
|
||||
jinja2/__pycache__/_identifier.cpython-37.pyc,,
|
||||
jinja2/__pycache__/asyncfilters.cpython-37.pyc,,
|
||||
jinja2/__pycache__/asyncsupport.cpython-37.pyc,,
|
||||
jinja2/__pycache__/bccache.cpython-37.pyc,,
|
||||
jinja2/__pycache__/compiler.cpython-37.pyc,,
|
||||
jinja2/__pycache__/constants.cpython-37.pyc,,
|
||||
jinja2/__pycache__/debug.cpython-37.pyc,,
|
||||
jinja2/__pycache__/defaults.cpython-37.pyc,,
|
||||
jinja2/__pycache__/environment.cpython-37.pyc,,
|
||||
jinja2/__pycache__/exceptions.cpython-37.pyc,,
|
||||
jinja2/__pycache__/ext.cpython-37.pyc,,
|
||||
jinja2/__pycache__/filters.cpython-37.pyc,,
|
||||
jinja2/__pycache__/idtracking.cpython-37.pyc,,
|
||||
jinja2/__pycache__/lexer.cpython-37.pyc,,
|
||||
jinja2/__pycache__/loaders.cpython-37.pyc,,
|
||||
jinja2/__pycache__/meta.cpython-37.pyc,,
|
||||
jinja2/__pycache__/nativetypes.cpython-37.pyc,,
|
||||
jinja2/__pycache__/nodes.cpython-37.pyc,,
|
||||
jinja2/__pycache__/optimizer.cpython-37.pyc,,
|
||||
jinja2/__pycache__/parser.cpython-37.pyc,,
|
||||
jinja2/__pycache__/runtime.cpython-37.pyc,,
|
||||
jinja2/__pycache__/sandbox.cpython-37.pyc,,
|
||||
jinja2/__pycache__/tests.cpython-37.pyc,,
|
||||
jinja2/__pycache__/utils.cpython-37.pyc,,
|
||||
jinja2/__pycache__/visitor.cpython-37.pyc,,
|
||||
jinja2/_compat.py,sha256=B6Se8HjnXVpzz9-vfHejn-DV2NjaVK-Iewupc5kKlu8,3191
|
||||
jinja2/_identifier.py,sha256=EdgGJKi7O1yvr4yFlvqPNEqV6M1qHyQr8Gt8GmVTKVM,1775
|
||||
jinja2/asyncfilters.py,sha256=8uwjG1zgHTv3K4nEvsj4HXWkK4NsOlfx7-CcnCULDWw,4185
|
||||
jinja2/asyncsupport.py,sha256=ZBFsDLuq3Gtji3Ia87lcyuDbqaHZJRdtShZcqwpFnSQ,7209
|
||||
jinja2/bccache.py,sha256=3Pmp4jo65M9FQuIxdxoDBbEDFwe4acDMQf77nEJfrHA,12139
|
||||
jinja2/compiler.py,sha256=xCNpF7-xAduODbGKSVEyzU7XZGeLWHZr1cwcZTQob30,66236
|
||||
jinja2/constants.py,sha256=RR1sTzNzUmKco6aZicw4JpQpJGCuPuqm1h1YmCNUEFY,1458
|
||||
jinja2/debug.py,sha256=UmsW6OxNmbIGvIkwytOyM1NsZB6xJvl_nSz3VgNETUk,8597
|
||||
jinja2/defaults.py,sha256=85B6YUUCyWPSdrSeVhcqFVuu_bHUAQXeey--FIwSeVQ,1126
|
||||
jinja2/environment.py,sha256=XqCM_GmncAXPm--CxpRPVF6uV_sPKb0Q0jVa7Znry04,50605
|
||||
jinja2/exceptions.py,sha256=VjNLawcmf2ODffqVMCQK1cRmvFaUfQWF4u8ouP3QPcE,5425
|
||||
jinja2/ext.py,sha256=AtwL5O5enT_L3HR9-oBvhGyUTdGoyaqG_ICtnR_EVd4,26441
|
||||
jinja2/filters.py,sha256=4xEq1qfJ7burpHW5GyL6bkGomp0W47jOXg-HG5aLP-Y,41401
|
||||
jinja2/idtracking.py,sha256=J3O4VHsrbf3wzwiBc7Cro26kHb6_5kbULeIOzocchIU,9211
|
||||
jinja2/lexer.py,sha256=VeGdW_t82Le4H-jLy-hX6UeosLf7ApUq2kuUos8YF4Y,29942
|
||||
jinja2/loaders.py,sha256=UUy5ud3lNtGtnn8iorlF9o1FJ6UqZZKMxd0VGnnqMHI,20350
|
||||
jinja2/meta.py,sha256=QjyYhfNRD3QCXjBJpiPl9KgkEkGXJbAkCUq4-Ur10EQ,4131
|
||||
jinja2/nativetypes.py,sha256=Arb2_3IuM386vWZbGPY7DmxryrXg3WzXAEnaHJNdWa0,3576
|
||||
jinja2/nodes.py,sha256=YwErhE9plVWeoxTQPtMwl10wovsyBRY4x9eAVgtP6zg,31071
|
||||
jinja2/optimizer.py,sha256=gQLlMYzvQhluhzmAIFA1tXS0cwgWYOjprN-gTRcHVsc,1457
|
||||
jinja2/parser.py,sha256=fcfdqePNTNyvosIvczbytVA332qpsURvYnCGcjDHSkA,35660
|
||||
jinja2/runtime.py,sha256=94chnK20a1m1t5AaLWeuiTq6L3g3GLs6AxVPfbNXIHE,30582
|
||||
jinja2/sandbox.py,sha256=knayyUvXsZ-F0mk15mO2-ehK9gsw04UhB8td-iUOtLc,17127
|
||||
jinja2/tests.py,sha256=iO_Y-9Vo60zrVe1lMpSl5sKHqAxe2leZHC08OoZ8K24,4799
|
||||
jinja2/utils.py,sha256=26B9HI2lVWaHY8iOnQTJzAcCL4PYOLiA3V79dm3oOSE,22456
|
||||
jinja2/visitor.py,sha256=DUHupl0a4PGp7nxRtZFttUzAi1ccxzqc2hzetPYUz8U,3240
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1,3 +0,0 @@
|
||||
[babel.extractors]
|
||||
jinja2 = jinja2.ext:babel_extract [i18n]
|
||||
|
@ -1 +0,0 @@
|
||||
jinja2
|
@ -1,13 +0,0 @@
|
||||
Mako was created by Michael Bayer.
|
||||
|
||||
Major contributing authors include:
|
||||
|
||||
- Michael Bayer <mike_mp@zzzcomputing.com>
|
||||
- Geoffrey T. Dairiki <dairiki@dairiki.org>
|
||||
- Philip Jenvey <pjenvey@underboss.org>
|
||||
- David Peckam
|
||||
- Armin Ronacher
|
||||
- Ben Bangert <ben@groovie.org>
|
||||
- Ben Trofatter
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,19 +0,0 @@
|
||||
Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,82 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Mako
|
||||
Version: 1.1.2
|
||||
Summary: A super-fast templating language that borrows the best ideas from the existing templating languages.
|
||||
Home-page: https://www.makotemplates.org/
|
||||
Author: Mike Bayer
|
||||
Author-email: mike@zzzcomputing.com
|
||||
License: MIT
|
||||
Project-URL: Documentation, https://docs.makotemplates.org
|
||||
Project-URL: Issue Tracker, https://github.com/sqlalchemy/mako
|
||||
Keywords: templates
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Requires-Dist: MarkupSafe (>=0.9.2)
|
||||
Provides-Extra: babel
|
||||
Requires-Dist: Babel ; extra == 'babel'
|
||||
Provides-Extra: lingua
|
||||
Requires-Dist: lingua ; extra == 'lingua'
|
||||
|
||||
=========================
|
||||
Mako Templates for Python
|
||||
=========================
|
||||
|
||||
Mako is a template library written in Python. It provides a familiar, non-XML
|
||||
syntax which compiles into Python modules for maximum performance. Mako's
|
||||
syntax and API borrows from the best ideas of many others, including Django
|
||||
templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded
|
||||
Python (i.e. Python Server Page) language, which refines the familiar ideas
|
||||
of componentized layout and inheritance to produce one of the most
|
||||
straightforward and flexible models available, while also maintaining close
|
||||
ties to Python calling and scoping semantics.
|
||||
|
||||
Nutshell
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
<%inherit file="base.html"/>
|
||||
<%
|
||||
rows = [[v for v in range(0,10)] for row in range(0,10)]
|
||||
%>
|
||||
<table>
|
||||
% for row in rows:
|
||||
${makerow(row)}
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
<%def name="makerow(row)">
|
||||
<tr>
|
||||
% for name in row:
|
||||
<td>${name}</td>\
|
||||
% endfor
|
||||
</tr>
|
||||
</%def>
|
||||
|
||||
Philosophy
|
||||
===========
|
||||
|
||||
Python is a great scripting language. Don't reinvent the wheel...your templates can handle it !
|
||||
|
||||
Documentation
|
||||
==============
|
||||
|
||||
See documentation for Mako at https://docs.makotemplates.org/en/latest/
|
||||
|
||||
License
|
||||
========
|
||||
|
||||
Mako is licensed under an MIT-style license (see LICENSE).
|
||||
Other incorporated projects may be licensed under different licenses.
|
||||
All licenses allow for non-commercial and commercial use.
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
../../../bin/mako-render,sha256=hcT69q_NmFY5G8c2FRh1t7TfhjyYqH2B1-m-aMxY5Y4,237
|
||||
Mako-1.1.2.dist-info/AUTHORS,sha256=Io2Vw70mjYS7yFcUuJxhIGiMUQt8FWJuxiiwyUW1WRg,282
|
||||
Mako-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Mako-1.1.2.dist-info/LICENSE,sha256=R80NQbEJL5Fhz7Yp7RXlzqGFFEcQ_0YzpCge8Ij_Xec,1097
|
||||
Mako-1.1.2.dist-info/METADATA,sha256=fxw2oNdTkNQnafc1Enid-QapQv1OaYnqwtNDJoeihoo,2600
|
||||
Mako-1.1.2.dist-info/RECORD,,
|
||||
Mako-1.1.2.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
|
||||
Mako-1.1.2.dist-info/entry_points.txt,sha256=GSuruj6eMrGwr7dHBGOdDkmgTTUQXr5ZrQjMmkPclKA,603
|
||||
Mako-1.1.2.dist-info/top_level.txt,sha256=LItdH8cDPetpUu8rUyBG3DObS6h9Gcpr9j_WLj2S-R0,5
|
||||
mako/__init__.py,sha256=kukH4UZzZx0XHsTBrfQMJ2fxcncjreyZv2m6PzvPWAM,242
|
||||
mako/__pycache__/__init__.cpython-37.pyc,,
|
||||
mako/__pycache__/_ast_util.cpython-37.pyc,,
|
||||
mako/__pycache__/ast.cpython-37.pyc,,
|
||||
mako/__pycache__/cache.cpython-37.pyc,,
|
||||
mako/__pycache__/cmd.cpython-37.pyc,,
|
||||
mako/__pycache__/codegen.cpython-37.pyc,,
|
||||
mako/__pycache__/compat.cpython-37.pyc,,
|
||||
mako/__pycache__/exceptions.cpython-37.pyc,,
|
||||
mako/__pycache__/filters.cpython-37.pyc,,
|
||||
mako/__pycache__/lexer.cpython-37.pyc,,
|
||||
mako/__pycache__/lookup.cpython-37.pyc,,
|
||||
mako/__pycache__/parsetree.cpython-37.pyc,,
|
||||
mako/__pycache__/pygen.cpython-37.pyc,,
|
||||
mako/__pycache__/pyparser.cpython-37.pyc,,
|
||||
mako/__pycache__/runtime.cpython-37.pyc,,
|
||||
mako/__pycache__/template.cpython-37.pyc,,
|
||||
mako/__pycache__/util.cpython-37.pyc,,
|
||||
mako/_ast_util.py,sha256=QKXZC0DbpYefKhTrQZjLgjcNXlTgY38sbB-vmBR2HpU,20414
|
||||
mako/ast.py,sha256=T5KnOwZewqAfULULLLWp6joGD-j14SiCtrH1-KGJCpQ,6789
|
||||
mako/cache.py,sha256=N1VoKHul8K7RUwsGwoUL-HMtylDvrL6iGWNh7_AI1dc,7736
|
||||
mako/cmd.py,sha256=HZxSUsAFVHVrcWvb43Nh_vdbrGeJLFNTR6ejyhdZ0dc,2859
|
||||
mako/codegen.py,sha256=DoxSM34-305v0E4Ox7Y31nsVtKAmCEbRVC3BmNFy_54,47892
|
||||
mako/compat.py,sha256=08w8lB0Z3QKQi9vd4n4xUtjG_A3wOrk3QdvxkHlribY,3848
|
||||
mako/exceptions.py,sha256=ogXjpZO1beh37cWWa0pm4IHVNKsuNIUnqOjWznEKMLQ,13110
|
||||
mako/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
mako/ext/__pycache__/__init__.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/autohandler.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/babelplugin.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/beaker_cache.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/extract.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/linguaplugin.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/preprocessors.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/pygmentplugin.cpython-37.pyc,,
|
||||
mako/ext/__pycache__/turbogears.cpython-37.pyc,,
|
||||
mako/ext/autohandler.py,sha256=FJs1cY6Vz_NePboCUr-3STZY38btxFRZsPhMNe6NSms,1885
|
||||
mako/ext/babelplugin.py,sha256=EquybfGr6ffla72QapzkwTNpEwi_P87f1s9C7xNFuJw,2138
|
||||
mako/ext/beaker_cache.py,sha256=oDN-vSLeKfnAJKlPgrKKuHI-g7zszwd2y1uApBoOkeM,2599
|
||||
mako/ext/extract.py,sha256=oBx6lQqLOtDMu8YpBYK_klCZvMuVvbAAA3I-WUyTPXo,4616
|
||||
mako/ext/linguaplugin.py,sha256=Z8bV4RHjDJhqMApINSadycM1Xj-B2vB1_i3YN3l2KSc,1954
|
||||
mako/ext/preprocessors.py,sha256=TfHmG6EgzYumbCiFU06IHXG_n5y2sA6RFtDBNJ613M8,576
|
||||
mako/ext/pygmentplugin.py,sha256=wYJixnCqHJ7zHPT6gB3tGUg-R6yctFNpEhNIKbHHl-E,4951
|
||||
mako/ext/turbogears.py,sha256=BcKxkPpkeawkFqj6zS5sUQYt4I6LafRDYMLIDOg0ZPY,2165
|
||||
mako/filters.py,sha256=vzpdxOOXWco5_evH_6_9a8b92lHuDC7Sl3XZhFyIVV8,6063
|
||||
mako/lexer.py,sha256=pNKb5MVSzOdW0L2S97TYPFBATmHD_mo8Br9-5RSfIUM,16926
|
||||
mako/lookup.py,sha256=TQ-wx1DR8rj2HqsNJBsrS4ZqROwAeTRkw-LrTbSQxFc,12718
|
||||
mako/parsetree.py,sha256=epGi5wKtZA8LcpzdrEXl_jjPGPvuO-IjuDSAYoLAp4Y,19411
|
||||
mako/pygen.py,sha256=dKxVMCSPMaXbMTgQyd5_J7WvdzPpuUprufR4PS3cyqY,10073
|
||||
mako/pyparser.py,sha256=eU3-mgdrmj1cL9SgFxh1rvIFcio_6oJxoNJnyMuGiCI,7789
|
||||
mako/runtime.py,sha256=2fhZBgmnP3wrWlZAVd6PZCSeuuGVXVA8BmRdXs6VEDo,28040
|
||||
mako/template.py,sha256=hKYaXvRzqU7Map8wXaGTGXc8gPl8EDF4WqoNpIF-EqQ,26558
|
||||
mako/util.py,sha256=5DoK9dvPpzFK6ZnL3hhzMHQ0meanhXrH8aHoO8fbkCs,11038
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1,20 +0,0 @@
|
||||
|
||||
[python.templating.engines]
|
||||
mako = mako.ext.turbogears:TGPlugin
|
||||
|
||||
[pygments.lexers]
|
||||
mako = mako.ext.pygmentplugin:MakoLexer
|
||||
html+mako = mako.ext.pygmentplugin:MakoHtmlLexer
|
||||
xml+mako = mako.ext.pygmentplugin:MakoXmlLexer
|
||||
js+mako = mako.ext.pygmentplugin:MakoJavascriptLexer
|
||||
css+mako = mako.ext.pygmentplugin:MakoCssLexer
|
||||
|
||||
[babel.extractors]
|
||||
mako = mako.ext.babelplugin:extract [babel]
|
||||
|
||||
[lingua.extractors]
|
||||
mako = mako.ext.linguaplugin:LinguaMakoExtractor [lingua]
|
||||
|
||||
[console_scripts]
|
||||
mako-render = mako.cmd:cmdline
|
||||
|
@ -1 +0,0 @@
|
||||
mako
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,28 +0,0 @@
|
||||
Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,103 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: MarkupSafe
|
||||
Version: 1.1.1
|
||||
Summary: Safely add untrusted strings to HTML/XML markup.
|
||||
Home-page: https://palletsprojects.com/p/markupsafe/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: The Pallets Team
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
||||
Project-URL: Code, https://github.com/pallets/markupsafe
|
||||
Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
|
||||
|
||||
MarkupSafe
|
||||
==========
|
||||
|
||||
MarkupSafe implements a text object that escapes characters so it is
|
||||
safe to use in HTML and XML. Characters that have special meanings are
|
||||
replaced so that they display as the actual characters. This mitigates
|
||||
injection attacks, meaning untrusted user input can safely be displayed
|
||||
on a page.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
pip install -U MarkupSafe
|
||||
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from markupsafe import Markup, escape
|
||||
>>> # escape replaces special characters and wraps in Markup
|
||||
>>> escape('<script>alert(document.cookie);</script>')
|
||||
Markup(u'<script>alert(document.cookie);</script>')
|
||||
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
||||
>>> Markup('<strong>Hello</strong>')
|
||||
Markup('<strong>hello</strong>')
|
||||
>>> escape(Markup('<strong>Hello</strong>'))
|
||||
Markup('<strong>hello</strong>')
|
||||
>>> # Markup is a text subclass (str on Python 3, unicode on Python 2)
|
||||
>>> # methods and operators escape their arguments
|
||||
>>> template = Markup("Hello <em>%s</em>")
|
||||
>>> template % '"World"'
|
||||
Markup('Hello <em>"World"</em>')
|
||||
|
||||
|
||||
Donate
|
||||
------
|
||||
|
||||
The Pallets organization develops and supports MarkupSafe and other
|
||||
libraries that use it. In order to grow the community of contributors
|
||||
and users, and allow the maintainers to devote more time to the
|
||||
projects, `please donate today`_.
|
||||
|
||||
.. _please donate today: https://palletsprojects.com/donate
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
* Website: https://palletsprojects.com/p/markupsafe/
|
||||
* Documentation: https://markupsafe.palletsprojects.com/
|
||||
* License: `BSD-3-Clause <https://github.com/pallets/markupsafe/blob/master/LICENSE.rst>`_
|
||||
* Releases: https://pypi.org/project/MarkupSafe/
|
||||
* Code: https://github.com/pallets/markupsafe
|
||||
* Issue tracker: https://github.com/pallets/markupsafe/issues
|
||||
* Test status:
|
||||
|
||||
* Linux, Mac: https://travis-ci.org/pallets/markupsafe
|
||||
* Windows: https://ci.appveyor.com/project/pallets/markupsafe
|
||||
|
||||
* Test coverage: https://codecov.io/gh/pallets/markupsafe
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
MarkupSafe-1.1.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||
MarkupSafe-1.1.1.dist-info/METADATA,sha256=nJHwJ4_4ka-V39QH883jPrslj6inNdyyNASBXbYgHXQ,3570
|
||||
MarkupSafe-1.1.1.dist-info/RECORD,,
|
||||
MarkupSafe-1.1.1.dist-info/WHEEL,sha256=GMu0CcHnECe7JSPnzBUPyOsrcZoHb7dOBGXgpe8vHSQ,104
|
||||
MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
||||
markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126
|
||||
markupsafe/__pycache__/__init__.cpython-37.pyc,,
|
||||
markupsafe/__pycache__/_compat.cpython-37.pyc,,
|
||||
markupsafe/__pycache__/_constants.cpython-37.pyc,,
|
||||
markupsafe/__pycache__/_native.cpython-37.pyc,,
|
||||
markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558
|
||||
markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690
|
||||
markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873
|
||||
markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884
|
||||
markupsafe/_speedups.cpython-37m-arm-linux-gnueabihf.so,sha256=UdHbkGis1TxK619S8APiKVHwcmcMKsR0rEA9WFeXTUs,46612
|
@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.32.3)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp37-cp37m-linux_armv7l
|
||||
|
@ -1 +0,0 @@
|
||||
markupsafe
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,19 +0,0 @@
|
||||
Copyright 2005-2020 SQLAlchemy authors and contributors <see AUTHORS file>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,195 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: SQLAlchemy
|
||||
Version: 1.3.17
|
||||
Summary: Database Abstraction Library
|
||||
Home-page: http://www.sqlalchemy.org
|
||||
Author: Mike Bayer
|
||||
Author-email: mike_mp@zzzcomputing.com
|
||||
License: MIT
|
||||
Project-URL: Documentation, https://docs.sqlalchemy.org
|
||||
Project-URL: Issue Tracker, https://github.com/sqlalchemy/sqlalchemy/
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
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 :: 3.9
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Database :: Front-Ends
|
||||
Classifier: Operating System :: OS Independent
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Provides-Extra: mssql
|
||||
Requires-Dist: pyodbc ; extra == 'mssql'
|
||||
Provides-Extra: mssql_pymssql
|
||||
Requires-Dist: pymssql ; extra == 'mssql_pymssql'
|
||||
Provides-Extra: mssql_pyodbc
|
||||
Requires-Dist: pyodbc ; extra == 'mssql_pyodbc'
|
||||
Provides-Extra: mysql
|
||||
Requires-Dist: mysqlclient ; extra == 'mysql'
|
||||
Provides-Extra: oracle
|
||||
Requires-Dist: cx-oracle ; extra == 'oracle'
|
||||
Provides-Extra: postgresql
|
||||
Requires-Dist: psycopg2 ; extra == 'postgresql'
|
||||
Provides-Extra: postgresql_pg8000
|
||||
Requires-Dist: pg8000 ; extra == 'postgresql_pg8000'
|
||||
Provides-Extra: postgresql_psycopg2binary
|
||||
Requires-Dist: psycopg2-binary ; extra == 'postgresql_psycopg2binary'
|
||||
Provides-Extra: postgresql_psycopg2cffi
|
||||
Requires-Dist: psycopg2cffi ; extra == 'postgresql_psycopg2cffi'
|
||||
Provides-Extra: pymysql
|
||||
Requires-Dist: pymysql ; extra == 'pymysql'
|
||||
|
||||
SQLAlchemy
|
||||
==========
|
||||
|
||||
The Python SQL Toolkit and Object Relational Mapper
|
||||
|
||||
Introduction
|
||||
-------------
|
||||
|
||||
SQLAlchemy is the Python SQL toolkit and Object Relational Mapper
|
||||
that gives application developers the full power and
|
||||
flexibility of SQL. SQLAlchemy provides a full suite
|
||||
of well known enterprise-level persistence patterns,
|
||||
designed for efficient and high-performing database
|
||||
access, adapted into a simple and Pythonic domain
|
||||
language.
|
||||
|
||||
Major SQLAlchemy features include:
|
||||
|
||||
* An industrial strength ORM, built
|
||||
from the core on the identity map, unit of work,
|
||||
and data mapper patterns. These patterns
|
||||
allow transparent persistence of objects
|
||||
using a declarative configuration system.
|
||||
Domain models
|
||||
can be constructed and manipulated naturally,
|
||||
and changes are synchronized with the
|
||||
current transaction automatically.
|
||||
* A relationally-oriented query system, exposing
|
||||
the full range of SQL's capabilities
|
||||
explicitly, including joins, subqueries,
|
||||
correlation, and most everything else,
|
||||
in terms of the object model.
|
||||
Writing queries with the ORM uses the same
|
||||
techniques of relational composition you use
|
||||
when writing SQL. While you can drop into
|
||||
literal SQL at any time, it's virtually never
|
||||
needed.
|
||||
* A comprehensive and flexible system
|
||||
of eager loading for related collections and objects.
|
||||
Collections are cached within a session,
|
||||
and can be loaded on individual access, all
|
||||
at once using joins, or by query per collection
|
||||
across the full result set.
|
||||
* A Core SQL construction system and DBAPI
|
||||
interaction layer. The SQLAlchemy Core is
|
||||
separate from the ORM and is a full database
|
||||
abstraction layer in its own right, and includes
|
||||
an extensible Python-based SQL expression
|
||||
language, schema metadata, connection pooling,
|
||||
type coercion, and custom types.
|
||||
* All primary and foreign key constraints are
|
||||
assumed to be composite and natural. Surrogate
|
||||
integer primary keys are of course still the
|
||||
norm, but SQLAlchemy never assumes or hardcodes
|
||||
to this model.
|
||||
* Database introspection and generation. Database
|
||||
schemas can be "reflected" in one step into
|
||||
Python structures representing database metadata;
|
||||
those same structures can then generate
|
||||
CREATE statements right back out - all within
|
||||
the Core, independent of the ORM.
|
||||
|
||||
SQLAlchemy's philosophy:
|
||||
|
||||
* SQL databases behave less and less like object
|
||||
collections the more size and performance start to
|
||||
matter; object collections behave less and less like
|
||||
tables and rows the more abstraction starts to matter.
|
||||
SQLAlchemy aims to accommodate both of these
|
||||
principles.
|
||||
* An ORM doesn't need to hide the "R". A relational
|
||||
database provides rich, set-based functionality
|
||||
that should be fully exposed. SQLAlchemy's
|
||||
ORM provides an open-ended set of patterns
|
||||
that allow a developer to construct a custom
|
||||
mediation layer between a domain model and
|
||||
a relational schema, turning the so-called
|
||||
"object relational impedance" issue into
|
||||
a distant memory.
|
||||
* The developer, in all cases, makes all decisions
|
||||
regarding the design, structure, and naming conventions
|
||||
of both the object model as well as the relational
|
||||
schema. SQLAlchemy only provides the means
|
||||
to automate the execution of these decisions.
|
||||
* With SQLAlchemy, there's no such thing as
|
||||
"the ORM generated a bad query" - you
|
||||
retain full control over the structure of
|
||||
queries, including how joins are organized,
|
||||
how subqueries and correlation is used, what
|
||||
columns are requested. Everything SQLAlchemy
|
||||
does is ultimately the result of a developer-
|
||||
initiated decision.
|
||||
* Don't use an ORM if the problem doesn't need one.
|
||||
SQLAlchemy consists of a Core and separate ORM
|
||||
component. The Core offers a full SQL expression
|
||||
language that allows Pythonic construction
|
||||
of SQL constructs that render directly to SQL
|
||||
strings for a target database, returning
|
||||
result sets that are essentially enhanced DBAPI
|
||||
cursors.
|
||||
* Transactions should be the norm. With SQLAlchemy's
|
||||
ORM, nothing goes to permanent storage until
|
||||
commit() is called. SQLAlchemy encourages applications
|
||||
to create a consistent means of delineating
|
||||
the start and end of a series of operations.
|
||||
* Never render a literal value in a SQL statement.
|
||||
Bound parameters are used to the greatest degree
|
||||
possible, allowing query optimizers to cache
|
||||
query plans effectively and making SQL injection
|
||||
attacks a non-issue.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Latest documentation is at:
|
||||
|
||||
http://www.sqlalchemy.org/docs/
|
||||
|
||||
Installation / Requirements
|
||||
---------------------------
|
||||
|
||||
Full documentation for installation is at
|
||||
`Installation <http://www.sqlalchemy.org/docs/intro.html#installation>`_.
|
||||
|
||||
Getting Help / Development / Bug reporting
|
||||
------------------------------------------
|
||||
|
||||
Please refer to the `SQLAlchemy Community Guide <http://www.sqlalchemy.org/support.html>`_.
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
|
||||
Above all, SQLAlchemy places great emphasis on polite, thoughtful, and
|
||||
constructive communication between users and developers.
|
||||
Please see our current Code of Conduct at
|
||||
`Code of Conduct <http://www.sqlalchemy.org/codeofconduct.html>`_.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
SQLAlchemy is distributed under the `MIT license
|
||||
<http://www.opensource.org/licenses/mit-license.php>`_.
|
||||
|
||||
|
||||
|
@ -1,405 +0,0 @@
|
||||
SQLAlchemy-1.3.17.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
SQLAlchemy-1.3.17.dist-info/LICENSE,sha256=WG4lA_RQxK6BaWDKMtQTuCDHQWJpdWvZThIkXGD4WXI,1100
|
||||
SQLAlchemy-1.3.17.dist-info/METADATA,sha256=xcBflt2jZsh5GZQV77WLVJDaHeBAF3PCbg0kvAGFxKI,7341
|
||||
SQLAlchemy-1.3.17.dist-info/RECORD,,
|
||||
SQLAlchemy-1.3.17.dist-info/WHEEL,sha256=GMu0CcHnECe7JSPnzBUPyOsrcZoHb7dOBGXgpe8vHSQ,104
|
||||
SQLAlchemy-1.3.17.dist-info/top_level.txt,sha256=rp-ZgB7D8G11ivXON5VGPjupT1voYmWqkciDt5Uaw_Q,11
|
||||
sqlalchemy/__init__.py,sha256=QoFu5r-vTXw_u7p7onkV160CcUz2_3tmxTeuzYvsJ2k,4659
|
||||
sqlalchemy/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/events.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/exc.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/inspection.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/interfaces.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/log.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/processors.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/schema.cpython-37.pyc,,
|
||||
sqlalchemy/__pycache__/types.cpython-37.pyc,,
|
||||
sqlalchemy/connectors/__init__.py,sha256=78tsbgw8Kh1tPCC2te-KV7DqeE7gRzUE2Qq64XIoUkU,278
|
||||
sqlalchemy/connectors/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/connectors/__pycache__/mxodbc.cpython-37.pyc,,
|
||||
sqlalchemy/connectors/__pycache__/pyodbc.cpython-37.pyc,,
|
||||
sqlalchemy/connectors/__pycache__/zxJDBC.cpython-37.pyc,,
|
||||
sqlalchemy/connectors/mxodbc.py,sha256=h_fyp3zVvJ22bBhHl0296MtieO977XHVhbugT9sYrFo,5352
|
||||
sqlalchemy/connectors/pyodbc.py,sha256=xR_EfAvOqA_qXLgTlWQ7m8dUtHKErZY3ZI0N5t7wj2g,5586
|
||||
sqlalchemy/connectors/zxJDBC.py,sha256=wJlwdsmRov3naSY71JvifytEC4lPqO5_eiF_K9UDb3E,1878
|
||||
sqlalchemy/cprocessors.cpython-37m-arm-linux-gnueabihf.so,sha256=b3bL8vUTD9dD_0J-eDS8GK1ZuLN6QvoCPvg_oto_C78,49424
|
||||
sqlalchemy/cresultproxy.cpython-37m-arm-linux-gnueabihf.so,sha256=KErxAJkXTEXyiuWtD8qpfUgyHyW9nZ3cKULg373VZcg,57836
|
||||
sqlalchemy/cutils.cpython-37m-arm-linux-gnueabihf.so,sha256=eyykgO7az8k5BbMu0HNSAzEQfaKxRcUNeIhDDuCFsYI,31952
|
||||
sqlalchemy/databases/__init__.py,sha256=IywgDc8lo4rrxtHR7u1S1ttUMTKrKpYS3wwnd8bISQA,819
|
||||
sqlalchemy/databases/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/__init__.py,sha256=2Cra66jK1L9BzcAJUhVaJXR0vPG06L3MI6GEh-b69KI,1909
|
||||
sqlalchemy/dialects/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/firebird/__init__.py,sha256=xiywqBgVlgc1yaV-IlwJdgLXhAb9ise-B-vfcoFzQLw,1152
|
||||
sqlalchemy/dialects/firebird/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/firebird/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/firebird/__pycache__/fdb.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/firebird/__pycache__/kinterbasdb.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/firebird/base.py,sha256=wml5psIvyvrLsBGFne--M2sHjEYbPRamcr5L3QuS-0w,30221
|
||||
sqlalchemy/dialects/firebird/fdb.py,sha256=kQQ3atPmEdsgxqtYBRZwg0HGitQiS5-VtL2f13WDWpI,4079
|
||||
sqlalchemy/dialects/firebird/kinterbasdb.py,sha256=X7UfqENJaVFJaQj_7dK7NyxmGU8bvAfKkv5m2lQl4rs,6437
|
||||
sqlalchemy/dialects/mssql/__init__.py,sha256=OMkEnG7PSHt4ee_P0DKfhXG1jLh5nzRuvxqKLfYLPO8,1812
|
||||
sqlalchemy/dialects/mssql/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/adodbapi.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/information_schema.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/mxodbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/pymssql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/pyodbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/__pycache__/zxjdbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mssql/adodbapi.py,sha256=u8QnHUI6C5nImuzyuk25D6oiBAQRjspM5SGjLySse1s,2719
|
||||
sqlalchemy/dialects/mssql/base.py,sha256=L7oD-TAPER0rKsdWJUr4fCbHzQ1IsX9JRJYtDlyQCpw,89821
|
||||
sqlalchemy/dialects/mssql/information_schema.py,sha256=plSgus0f7PsR28oTB8y4-UkXU43rTxh0ltaFRvua9-A,5639
|
||||
sqlalchemy/dialects/mssql/mxodbc.py,sha256=geB0M9CAYo0AbPgiGLhWEGmx76B5SNGcQJ_PDl5yJMw,4616
|
||||
sqlalchemy/dialects/mssql/provision.py,sha256=0WXdFXwePVPYVrV3mmbbiAkuj-Tv5Rr-i3aizbD6Z7w,2786
|
||||
sqlalchemy/dialects/mssql/pymssql.py,sha256=RmV43rpu7EqMcNCsA31L9uRT272e9p0juEO6crBoaS0,4677
|
||||
sqlalchemy/dialects/mssql/pyodbc.py,sha256=xNeG4Cf489s1NPApg53ckpOSI1d3Plg6Ql0lZv4sF2A,14823
|
||||
sqlalchemy/dialects/mssql/zxjdbc.py,sha256=zxUozig0SWOlC6JuqzuyG6ojI55oI44P1RkaToWYul4,2311
|
||||
sqlalchemy/dialects/mysql/__init__.py,sha256=9mlm4mqt_CxcbFh9KC38Srw0_OnvrSluBmOcaWoOlV8,2056
|
||||
sqlalchemy/dialects/mysql/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/cymysql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/dml.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/enumerated.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/gaerdbms.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/json.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/mysqlconnector.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/mysqldb.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/oursql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/pymysql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/pyodbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/reflection.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/types.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/__pycache__/zxjdbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/mysql/base.py,sha256=hMSuQKFrZZnpOQ1eFLOHCmB5Nl3OrhllNE13k3kxDls,101213
|
||||
sqlalchemy/dialects/mysql/cymysql.py,sha256=iZIQWKba3Ap6N6Af5MEtCgHN4SoHSUKFJwD_3gktsME,2245
|
||||
sqlalchemy/dialects/mysql/dml.py,sha256=yq9Kgm2IvLkt0_Uw1RGsuyjNQVgpWIWMFd2Ntm_R65Y,4764
|
||||
sqlalchemy/dialects/mysql/enumerated.py,sha256=9hhAfnVzvFjXKEShwqp52XT6Kaq8aw4uD7CD6doPd6k,11307
|
||||
sqlalchemy/dialects/mysql/gaerdbms.py,sha256=khU9l7SolzCyhF7d7q1iBn_OhPj3gw3IqGGtzomsugo,3375
|
||||
sqlalchemy/dialects/mysql/json.py,sha256=AJ_-DkzgByPy-3XQhXms2JiTM7MxGr2Le6E4k2-eT50,2050
|
||||
sqlalchemy/dialects/mysql/mysqlconnector.py,sha256=2piMPvg48daNXr2XzpLwmMm1VYVs9mw0AJ43OLXQgvI,7889
|
||||
sqlalchemy/dialects/mysql/mysqldb.py,sha256=aSkj-xdGYIhPlH2sOvGOo0qrbX3lkR1r8RX-84Rxe4Q,8383
|
||||
sqlalchemy/dialects/mysql/oursql.py,sha256=GzFBpEZGwWnLPVmC4IlU5_Y9gZvc-8-44-s6Xo2BXpg,8086
|
||||
sqlalchemy/dialects/mysql/provision.py,sha256=sJ7IpiIB1Eb9AdRK3loRlsCHKzzsFGJzMgICyRrkFpY,1269
|
||||
sqlalchemy/dialects/mysql/pymysql.py,sha256=8-V0VEWKOv1ooPQgRnm2Piqkk1lAqVDq16wZQB-xq58,2440
|
||||
sqlalchemy/dialects/mysql/pyodbc.py,sha256=0UdZSRnCF-0EWsX36Azrvc15xE87YEzyJSSGQJqVx0U,3470
|
||||
sqlalchemy/dialects/mysql/reflection.py,sha256=FgrerZD3x-KkXh5XbfYrPfNf_zNKFUVSRqW9Lv2iKjI,18267
|
||||
sqlalchemy/dialects/mysql/types.py,sha256=sOIRc3hnpuYVOQZyDadJjigJvA3rjaz66yD4_dAibS4,24601
|
||||
sqlalchemy/dialects/mysql/zxjdbc.py,sha256=u-jcqk3ZnpuPv89Hv3iEiCEhN0Ck4J48OLSYChZ3H-s,3970
|
||||
sqlalchemy/dialects/oracle/__init__.py,sha256=0800ZWZlvJfZ8qd_K4OfDEUq0TnAL7WkvaJPkMLiRDU,1257
|
||||
sqlalchemy/dialects/oracle/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/oracle/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/oracle/__pycache__/cx_oracle.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/oracle/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/oracle/__pycache__/zxjdbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/oracle/base.py,sha256=x6GAt5W6R6MXOx5JMn5mALccY387sBMAgzPY_ev-kB8,76224
|
||||
sqlalchemy/dialects/oracle/cx_oracle.py,sha256=dZT9x1zkopNAk0SYbn8X06mDXZo2Z34qXmR2fwOYVFU,44915
|
||||
sqlalchemy/dialects/oracle/provision.py,sha256=zpAooUqZY741vrjplNkxV2v3uf4kbZb3r_LfH9dKkJw,3862
|
||||
sqlalchemy/dialects/oracle/zxjdbc.py,sha256=eBqslfHL08YaEUzZ32-faQo9nxLCR3s8IadVAI200FY,8207
|
||||
sqlalchemy/dialects/postgresql/__init__.py,sha256=G0qS6NaThvmq48RH378d90vBbfglrgKt_LxuGyq8UAM,2461
|
||||
sqlalchemy/dialects/postgresql/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/array.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/dml.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/ext.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/hstore.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/json.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/pg8000.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/psycopg2.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/psycopg2cffi.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/pygresql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/pypostgresql.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/ranges.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/__pycache__/zxjdbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/postgresql/array.py,sha256=XrpqVaX2xvF8poI5CyD6gIq-3XgoSqIEeBwU_BSA41I,12043
|
||||
sqlalchemy/dialects/postgresql/base.py,sha256=gTzhOkwkXn7pmSWfvxqDorNq1A4r_h994eNdyBYTIs0,124341
|
||||
sqlalchemy/dialects/postgresql/dml.py,sha256=JWLLh1Z9Kuu6TgReIFMKqOHoQBwc0xDqzIwRLik7Yoc,7790
|
||||
sqlalchemy/dialects/postgresql/ext.py,sha256=-lBaLXWbzapvozj1I8yP47GGtTmjXYPjnInJOTuHHTU,6905
|
||||
sqlalchemy/dialects/postgresql/hstore.py,sha256=p62Vdg4REY-p4B3Y6dsIekj85vqMqEVj2DWUn8Z6Iig,12443
|
||||
sqlalchemy/dialects/postgresql/json.py,sha256=MihPxRbtlVN54ya9EaDGHiB3IS2icpXmQVb7Vwol-e0,10132
|
||||
sqlalchemy/dialects/postgresql/pg8000.py,sha256=bQI9hm4lr4JshUlFWSDpAYBWXsMCsgWyETkSZPDexJg,9722
|
||||
sqlalchemy/dialects/postgresql/provision.py,sha256=E8LOoSNSWUlx77ihNLQfW9csAxsmL-qleiLPbVlSlVw,2008
|
||||
sqlalchemy/dialects/postgresql/psycopg2.py,sha256=2H7YaVaNkitKwYlHztS5iAX5kjAvu2tHHevpbfAUgJ8,35979
|
||||
sqlalchemy/dialects/postgresql/psycopg2cffi.py,sha256=8X5uLoW2am61rqwYs0agfngZ8awYia7AAnbgWwDF27w,1657
|
||||
sqlalchemy/dialects/postgresql/pygresql.py,sha256=eyRnGRlqeEbiwYbhcazQUkyHnB4yCeh9c7nhnQyPJ8E,8129
|
||||
sqlalchemy/dialects/postgresql/pypostgresql.py,sha256=9giPOxOzVlJHc7r4g-YsVsFWONZQQjIi_mVWzKopI2c,2915
|
||||
sqlalchemy/dialects/postgresql/ranges.py,sha256=vvc2NmQsprM81VZeO1zukk4D_T3GTWJ_MoFa7E2chHE,4478
|
||||
sqlalchemy/dialects/postgresql/zxjdbc.py,sha256=YMtRIy1IbMVMQKMxa_gORzXHbkEVxiJVBpeg4IFuYvM,1415
|
||||
sqlalchemy/dialects/sqlite/__init__.py,sha256=EvPKdQyHTkXlziZo6wYrJ2D1V8Pa52zK5kb2I59uX4s,1042
|
||||
sqlalchemy/dialects/sqlite/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/__pycache__/json.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/__pycache__/pysqlcipher.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/__pycache__/pysqlite.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sqlite/base.py,sha256=_cBzmfDarBg5tO13VoH0dZgSrN58Rn4UfrM1oH4fuXs,72609
|
||||
sqlalchemy/dialects/sqlite/json.py,sha256=IwhCnGL_BKtASpm0-OzeNByp3qtkcLZgAeBGY_EPUvM,2292
|
||||
sqlalchemy/dialects/sqlite/provision.py,sha256=PEmgxbdz67KsONOEhFVQFLX3s4BXWKLb2gvNgj0gn9M,2591
|
||||
sqlalchemy/dialects/sqlite/pysqlcipher.py,sha256=RwePrdk3xrEg2c0vpFQSos6823EKEHJKrF-jgo7mYrE,4692
|
||||
sqlalchemy/dialects/sqlite/pysqlite.py,sha256=wDRcXcw8JFnGjbeu4qAeEp1vK8M_z86vY8Ls4AOSzEI,20983
|
||||
sqlalchemy/dialects/sybase/__init__.py,sha256=W9wFI2eRTBJVLaoplH5esmiITkz9LiNa-nDhiG8DwpM,1363
|
||||
sqlalchemy/dialects/sybase/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sybase/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sybase/__pycache__/mxodbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sybase/__pycache__/pyodbc.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sybase/__pycache__/pysybase.cpython-37.pyc,,
|
||||
sqlalchemy/dialects/sybase/base.py,sha256=N1G5tUKOtBjeOXeRciZP6iui1M8CYWFW9KchA-qDi_s,31953
|
||||
sqlalchemy/dialects/sybase/mxodbc.py,sha256=LqEEcLRrXuLICWLpg2ePgczZhuGzU20JsO2j_W3M2Ho,902
|
||||
sqlalchemy/dialects/sybase/pyodbc.py,sha256=013aGwoG1C19S_v4lPSZj4ComdPrdlwSMH8F7pjyMS8,2120
|
||||
sqlalchemy/dialects/sybase/pysybase.py,sha256=7iF-t7qfR5VGNeYzHkDoPNthUAJGSAIjeLwXrC5BJQE,3313
|
||||
sqlalchemy/engine/__init__.py,sha256=YTdumyq5iYjIsQ1P1FDgTDnEPqZgGasCao6k15prmUw,24256
|
||||
sqlalchemy/engine/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/default.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/interfaces.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/reflection.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/result.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/strategies.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/threadlocal.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/url.cpython-37.pyc,,
|
||||
sqlalchemy/engine/__pycache__/util.cpython-37.pyc,,
|
||||
sqlalchemy/engine/base.py,sha256=k5WVUNgasJE56I3nMvW8sAfap3UTuGxzXz9L4lwrSXM,87719
|
||||
sqlalchemy/engine/default.py,sha256=r4NyJf2d6qVcBgQrh1c5PWxdcg1FI0KhCms_1nQXcw0,54994
|
||||
sqlalchemy/engine/interfaces.py,sha256=AzkS3nGoNk3VI85GPiDFb7ugSmPdWTYpMHI9MmC0AdQ,46993
|
||||
sqlalchemy/engine/reflection.py,sha256=Ccbz18UE3XJrGShy5ZSa6S-PZTkIfn-WTVsOsuwTktg,34561
|
||||
sqlalchemy/engine/result.py,sha256=1-nFJlpdlJFODmmGaQrRF1R3UDS3X8EUEhGHtPHLs4A,54716
|
||||
sqlalchemy/engine/strategies.py,sha256=BuDOCGp6TMAej65TOresW9VHW2VfS60hx-rH4WfDPis,9847
|
||||
sqlalchemy/engine/threadlocal.py,sha256=EsPbaSO4S8WU4beLAyZ22iHV5YfxXt4ZejxuSMTu6pI,4764
|
||||
sqlalchemy/engine/url.py,sha256=PjgwmYtCr7CHP2TCiZBoOgctTjS7zK7GMMShPoQLBmU,9411
|
||||
sqlalchemy/engine/util.py,sha256=wDnfhJyQyxToapCC1jw6FRyW006dnChVIXYBIavzGF4,2421
|
||||
sqlalchemy/event/__init__.py,sha256=BuOhHzdZQnfPwXK3cvVUbsGJ7vhwwRzN673a8ImEPlA,596
|
||||
sqlalchemy/event/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/event/__pycache__/api.cpython-37.pyc,,
|
||||
sqlalchemy/event/__pycache__/attr.cpython-37.pyc,,
|
||||
sqlalchemy/event/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/event/__pycache__/legacy.cpython-37.pyc,,
|
||||
sqlalchemy/event/__pycache__/registry.cpython-37.pyc,,
|
||||
sqlalchemy/event/api.py,sha256=FeyGUN3Gtwh3g7JQTlDnn1zuILSWd-lEwb4Rvk7Eez0,7085
|
||||
sqlalchemy/event/attr.py,sha256=k4tXlwyPpXaAFyHp11nk7I9ZV4yEFgNpESGMt9Er1BQ,13853
|
||||
sqlalchemy/event/base.py,sha256=stD9Z3dWlFTDSFqcViREtgf4c8omBs2rvyeFEOXwi1g,9753
|
||||
sqlalchemy/event/legacy.py,sha256=T9ZOjmibgXCOqW2XADc1nsXxbS159ZYl2ueRUEfsZrU,5904
|
||||
sqlalchemy/event/registry.py,sha256=xA0dKdRoyE7mz3m4uhQDZ7nxC0LVWfPDOxjzxpPX0m8,8243
|
||||
sqlalchemy/events.py,sha256=7pAnJ3mPX7O-C7yPU7gQmBW5Zv-S8dcvY01NrUK3AHU,53052
|
||||
sqlalchemy/exc.py,sha256=lfTTGCfcvq8ibrgA7c0rbwQQTgO1gzm8EhMB_eY8fW4,17361
|
||||
sqlalchemy/ext/__init__.py,sha256=A8EjxtBgEW-qCJX0qqqo3OUJQe9sjjBYPYw5dN866bE,322
|
||||
sqlalchemy/ext/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/associationproxy.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/automap.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/baked.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/compiler.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/horizontal_shard.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/hybrid.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/indexable.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/instrumentation.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/mutable.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/orderinglist.cpython-37.pyc,,
|
||||
sqlalchemy/ext/__pycache__/serializer.cpython-37.pyc,,
|
||||
sqlalchemy/ext/associationproxy.py,sha256=8TpfZ8gA3X0lI7eDqVex7wySKxjcqcaIJJlM0qkRpTU,49768
|
||||
sqlalchemy/ext/automap.py,sha256=4g3HrD-jyJ1LctT3O4iTNLAYVPrP4OwdMCruQrXbLiI,42157
|
||||
sqlalchemy/ext/baked.py,sha256=7fjqFZhTGXe5C1cDw4Y-ldO8hWLzCxYacUDsx5TzXSo,21989
|
||||
sqlalchemy/ext/compiler.py,sha256=q5kP9F7PaReG7HEx1H5P0EuwN0mJ25Uk-KutMfuj-JY,17147
|
||||
sqlalchemy/ext/declarative/__init__.py,sha256=7c0OfggXwiLSVvehkwJJDDunv3AuY6Kq-4eMuNT-VNA,902
|
||||
sqlalchemy/ext/declarative/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/ext/declarative/__pycache__/api.cpython-37.pyc,,
|
||||
sqlalchemy/ext/declarative/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/ext/declarative/__pycache__/clsregistry.cpython-37.pyc,,
|
||||
sqlalchemy/ext/declarative/api.py,sha256=9clomjjILIdqQGE8x2kgZdRxjfRfM27WbdjMoSs7mNE,27636
|
||||
sqlalchemy/ext/declarative/base.py,sha256=vAVhpcwXCXFhQ_Yl-yL6D1ypnmogue4AW4CHgCXgQQI,32093
|
||||
sqlalchemy/ext/declarative/clsregistry.py,sha256=Nvxdt0KmYDIscE7V9tUEpDauf4EEc6dFZLiS2Cx0Cdo,12049
|
||||
sqlalchemy/ext/horizontal_shard.py,sha256=fBwLdomhyoa5iBVRaealC5TUzcm64Qx8QXTVGIf3SaA,9138
|
||||
sqlalchemy/ext/hybrid.py,sha256=JCyVxtk3ZSTGsIXFCjiNY4OxXGA_K4r9FRBhTGF6FJE,40325
|
||||
sqlalchemy/ext/indexable.py,sha256=pj8WNfIe_YsOIqFsel_93sMzTNsA9Rg03mGs11UNA3E,11254
|
||||
sqlalchemy/ext/instrumentation.py,sha256=7pxb7SDAnFvtHUxXnx8rqg4XKCadnWDGOBzFQHqeBS8,14351
|
||||
sqlalchemy/ext/mutable.py,sha256=qPhBEnRCj3GuRUF1a44J9jEdcvfsDCcgeGzZN_eSOHM,31820
|
||||
sqlalchemy/ext/orderinglist.py,sha256=sOdhObx8L8E7-LV2nSwRFOYFJK5hcz-g7K8gNKKewms,13900
|
||||
sqlalchemy/ext/serializer.py,sha256=ece4dfFCNbKgg-PbzDG_vZXM3C04w-C1REpF9h6INgQ,5784
|
||||
sqlalchemy/inspection.py,sha256=d4_LstciZQ766aPV5E8DlVI922f7eZ5L4rSMOCECyB4,3031
|
||||
sqlalchemy/interfaces.py,sha256=F8zw_dufYkf7zfc2bxb00AZUmOuSr5zoiWqx3GCNWNk,12740
|
||||
sqlalchemy/log.py,sha256=9K0QmnWqg4YTKdHkcJpudvdNsY2m9LmH5MKxj9INqlU,6705
|
||||
sqlalchemy/orm/__init__.py,sha256=PxbRLhF3nBDgTh198el-akJ29gsu0X6ooF1pZKk11zs,9558
|
||||
sqlalchemy/orm/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/attributes.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/collections.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/dependency.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/deprecated_interfaces.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/descriptor_props.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/dynamic.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/evaluator.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/events.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/exc.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/identity.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/instrumentation.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/interfaces.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/loading.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/mapper.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/path_registry.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/persistence.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/properties.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/query.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/relationships.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/scoping.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/session.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/state.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/strategies.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/strategy_options.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/sync.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/unitofwork.cpython-37.pyc,,
|
||||
sqlalchemy/orm/__pycache__/util.cpython-37.pyc,,
|
||||
sqlalchemy/orm/attributes.py,sha256=F7bOBInY4KWB4erAeH3ImmUMJlyuDm4uNin1Qa6bD4Q,67867
|
||||
sqlalchemy/orm/base.py,sha256=8X7-3ZM5MYSAz1n_CYlIM2spYEELf_u9ZRdDqtuNYAE,15317
|
||||
sqlalchemy/orm/collections.py,sha256=CLeCvvSuoMpn7ms-2l0PUNADiUTjHvNAcuZz4-XJg_c,52683
|
||||
sqlalchemy/orm/dependency.py,sha256=02Jyovdu-dyQ6umen79zeggcYnocRk4QW4zT2StA4vs,46556
|
||||
sqlalchemy/orm/deprecated_interfaces.py,sha256=NoUlf7eCwxS2QB-IC_Gr1d6IplYpvXWSHuftu0gzvV0,20763
|
||||
sqlalchemy/orm/descriptor_props.py,sha256=S0EJbqAQFsMxGF7gMdZwjsZn4NACa-sinwWeV3XGqOs,28377
|
||||
sqlalchemy/orm/dynamic.py,sha256=GcrMj7Uwvmh2CD-OatPExTvY0H6DtysBcQfX89dwgs8,14666
|
||||
sqlalchemy/orm/evaluator.py,sha256=clC6Tf6Ppv-xwmDTAcNh5axOqrvrnzC5Jq7rowPo3kA,5441
|
||||
sqlalchemy/orm/events.py,sha256=dV_-UqtxyN-1mJvRhZOAoBvjl7SM_5Aq0kXI3Pdm5fw,104408
|
||||
sqlalchemy/orm/exc.py,sha256=G_szgGYDr2ojIaYk9-qAjQA6B3d5Kbi0tVTIgq5HHbs,6616
|
||||
sqlalchemy/orm/identity.py,sha256=7Jhn-byH1e-K7xihNaYEpQLEkUaTuvykR3seXY7ahgU,10436
|
||||
sqlalchemy/orm/instrumentation.py,sha256=b1CcLwYzBa_ppCimxruTDEdoUNuCp8M5lP3WxEdSOf4,18131
|
||||
sqlalchemy/orm/interfaces.py,sha256=7hJtC3irDY9htapLJdjzxKCCja8MBrJobOYn5UTG-NA,25851
|
||||
sqlalchemy/orm/loading.py,sha256=oITlYdKbQoqgfa8gZSxUukS4tdbYwffOW0NBaedXsdw,33847
|
||||
sqlalchemy/orm/mapper.py,sha256=Na8nmNbm110CzQ4-jleDDEe18BATT_rup63QJCIoGcY,129890
|
||||
sqlalchemy/orm/path_registry.py,sha256=AT4cnr3fvxo44FthmyKjzX7LTHrfdgOotr8jStycWXY,13764
|
||||
sqlalchemy/orm/persistence.py,sha256=nHp_TCPOfBQiNYj5s8Q3L0zesHQrcJ2WbUK87JPhPXI,65927
|
||||
sqlalchemy/orm/properties.py,sha256=xIKHjXzA42KL-FtoFWuUe_9xsos3zSbZ8vHEuAPzV5k,12695
|
||||
sqlalchemy/orm/query.py,sha256=wMWrOosgc8OHkvPQW-7t5PpEbwPaN_LVSqVQlr86Rjo,178949
|
||||
sqlalchemy/orm/relationships.py,sha256=fdvc1ds4mbUN50gP7jyStuM-KMNX5bd1clzj6PsQ8Io,136637
|
||||
sqlalchemy/orm/scoping.py,sha256=F-RHAC3Ynw3kl_kwfalr8dGoiN50oyunXUGL0Tyz3U4,6414
|
||||
sqlalchemy/orm/session.py,sha256=CM-KKA5iWl6ozqsV0-iEoFQqBe4XP4OIdIVbiEvuV_4,131284
|
||||
sqlalchemy/orm/state.py,sha256=ZCEcx38aRsD3aCWF1XUiaGajFcYUjlDWK4sXfzsDe58,30794
|
||||
sqlalchemy/orm/strategies.py,sha256=M1ECN149rJRIWyTZopF3eeuBewEh207JKOkIYlOO4Dg,87001
|
||||
sqlalchemy/orm/strategy_options.py,sha256=1ggl_tsAjg37ors2cfoNN3mFxwepoSEe43gI3bPB3Oc,57376
|
||||
sqlalchemy/orm/sync.py,sha256=564q5ie_-aOiswgHZtaK-pnB8sCfzakOXte_V9V27Dk,5823
|
||||
sqlalchemy/orm/unitofwork.py,sha256=OAYzkT_p5Yul4krfnZTuN84zuuYxGe1EzZCOkdpeocI,24735
|
||||
sqlalchemy/orm/util.py,sha256=FLVsN4QcZP5pIptjJ4CcdMyd0xTbA7NnIftu89KkV0g,45432
|
||||
sqlalchemy/pool/__init__.py,sha256=-Vflck_t3sr66dgA4mehtNPZdvOsK7CgkjvY7UC7CbY,1483
|
||||
sqlalchemy/pool/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/pool/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/pool/__pycache__/dbapi_proxy.cpython-37.pyc,,
|
||||
sqlalchemy/pool/__pycache__/impl.cpython-37.pyc,,
|
||||
sqlalchemy/pool/base.py,sha256=-RL2p09Jx_X-kxmDltHdyG2cCSmYCrSDAELLNnFjd4g,36523
|
||||
sqlalchemy/pool/dbapi_proxy.py,sha256=zKCnvTcKfKuf04zqPMDjuuLtmdpIbkIKnk4dICLg_WA,4320
|
||||
sqlalchemy/pool/impl.py,sha256=oJYs7lUgfU7HbWp5VvTuHUXqBB1DSNTWuskevw6vNBA,14645
|
||||
sqlalchemy/processors.py,sha256=i_DiEYBHp5JJvvp7omB_TXSXf5efWTILvjVYvu8LHmw,5744
|
||||
sqlalchemy/schema.py,sha256=mkZmV4FQ4XWqRMsRoIf0lmB13bftAFPZjcszEKaE5gE,2418
|
||||
sqlalchemy/sql/__init__.py,sha256=12olVEiRBSf27BGAt_aWOUsLBF3sptfDvt-o-4K_7ts,3789
|
||||
sqlalchemy/sql/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/annotation.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/base.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/compiler.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/crud.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/ddl.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/default_comparator.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/dml.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/elements.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/expression.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/functions.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/naming.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/operators.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/schema.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/selectable.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/sqltypes.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/type_api.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/util.cpython-37.pyc,,
|
||||
sqlalchemy/sql/__pycache__/visitors.cpython-37.pyc,,
|
||||
sqlalchemy/sql/annotation.py,sha256=8XH8I_XmZI5iF2QwqX9N0auQCnh0EHZkOeoPiFQoUZM,6725
|
||||
sqlalchemy/sql/base.py,sha256=vDkZqV6Q-IigRLdEzf-IuQqHW6DeckQ5N85vbgzXpVA,21740
|
||||
sqlalchemy/sql/compiler.py,sha256=OkqHP1UOVR0fysEWdUFl44w9X582YDlOgKLTrkin2uc,126523
|
||||
sqlalchemy/sql/crud.py,sha256=ca_9Rjlxw_OnWZxBas_ElvMGtClvIUhLjxWOHhHJ6BE,25889
|
||||
sqlalchemy/sql/ddl.py,sha256=Mwfkqrc551QMnDeozZLRDu62je2SlP6ABXs6L9PGrtE,41416
|
||||
sqlalchemy/sql/default_comparator.py,sha256=tRDxI3AGdgrhG-hWymXgH2952Fqfw5f5-zB8Rbfq2qQ,12234
|
||||
sqlalchemy/sql/dml.py,sha256=YF3tCrAUdXskjLyUe5KPKlDp_zbCnujVlyGxa4MdQlk,35335
|
||||
sqlalchemy/sql/elements.py,sha256=dFZ8KSm_mFkYMJjEAEP3ipl3Uf0p0U3dpUQCFqE6GYs,159917
|
||||
sqlalchemy/sql/expression.py,sha256=BVhn2KBPg3CQBmBfKPQqvYMgTHqHkt_-bqej3RLSD-g,9209
|
||||
sqlalchemy/sql/functions.py,sha256=gxWSE5KoTnh7ylVLwPnmGwVKwvJY38VjMjdOOtsvXEI,35833
|
||||
sqlalchemy/sql/naming.py,sha256=zVMDaA0Npbe8NzBSVBykw69cobe-dfQDC4r451cpvUk,5889
|
||||
sqlalchemy/sql/operators.py,sha256=J7ghLip6g-S-xGjNTx5RBo-hjM48RZ9pqVI8dIUY77A,42548
|
||||
sqlalchemy/sql/schema.py,sha256=28UI94JEdxrJq8G3RnQj6x-f4pNIOwckhQaPfq_kKmg,172921
|
||||
sqlalchemy/sql/selectable.py,sha256=enoXrsZIMlmFFo3fTK5w3wCxEttTSIvXFjKG8jmPlRw,137999
|
||||
sqlalchemy/sql/sqltypes.py,sha256=edW3yywfapznqhcBfbcirbg_8Ow44HLKzar80eyl23M,100787
|
||||
sqlalchemy/sql/type_api.py,sha256=BhCUsW--YVXV2iCoA3eWao608YmNkFw8plEwR1dhb9A,52229
|
||||
sqlalchemy/sql/util.py,sha256=gnU_xzrrmhD4vJ2RG5qAmWCe-jqG7dkmGRr-t2t3ZTg,29192
|
||||
sqlalchemy/sql/visitors.py,sha256=frayBlJ-hGW5wWJJC_EwA0WXs-RJuKSVgJr-bJ-VAf4,15953
|
||||
sqlalchemy/testing/__init__.py,sha256=dvAdeVcRveMsKSxAV71HG_wyxNgUjvIg03zyasFaVCI,2789
|
||||
sqlalchemy/testing/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/assertions.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/assertsql.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/config.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/engines.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/entities.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/exclusions.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/fixtures.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/mock.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/pickleable.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/profiling.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/provision.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/replay_fixture.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/requirements.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/schema.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/util.cpython-37.pyc,,
|
||||
sqlalchemy/testing/__pycache__/warnings.cpython-37.pyc,,
|
||||
sqlalchemy/testing/assertions.py,sha256=bqhUma94aCjrAVS6_w2OOECkCClHkvV0YlOpo_mMZOU,19779
|
||||
sqlalchemy/testing/assertsql.py,sha256=Qss3YS3O0ac68rBh2FPGskgDd6yJzG_5KUn0UhhtQS0,13573
|
||||
sqlalchemy/testing/config.py,sha256=OQC0OW8r_rlj3Bljv03Vb1pVABJoLwM0MWUll-daaGk,5521
|
||||
sqlalchemy/testing/engines.py,sha256=vL6jvWWIXe5XJKCzx2NRkgeT6aNatiNdes_ZHbdH5pw,10437
|
||||
sqlalchemy/testing/entities.py,sha256=c40-zDP6Y6vx18Pmj9Lx4JZ26lr4dQ_42JoffyEP9cA,3203
|
||||
sqlalchemy/testing/exclusions.py,sha256=0hOS3GnCs9T149eB4fZfxtGSWsPU_bi1VAlLhldr16w,13037
|
||||
sqlalchemy/testing/fixtures.py,sha256=eMARL5rpAaypiTpiK8YCAUFOZztrTTWCoLyElMTUSNA,15034
|
||||
sqlalchemy/testing/mock.py,sha256=TMVhpHQtM3v-2CFNYsP6np2vsF7aNDMWXCnjfI9rNvI,893
|
||||
sqlalchemy/testing/pickleable.py,sha256=6JlSnkXCrbbjeHkbFBwdA8BBrYfLz-PVA7slVhGNYYE,2693
|
||||
sqlalchemy/testing/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
sqlalchemy/testing/plugin/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/testing/plugin/__pycache__/bootstrap.cpython-37.pyc,,
|
||||
sqlalchemy/testing/plugin/__pycache__/plugin_base.cpython-37.pyc,,
|
||||
sqlalchemy/testing/plugin/__pycache__/pytestplugin.cpython-37.pyc,,
|
||||
sqlalchemy/testing/plugin/bootstrap.py,sha256=0rkror_9S175GPGNnbtbDmfdLEhu9v-AAv715lR8KyU,1468
|
||||
sqlalchemy/testing/plugin/plugin_base.py,sha256=3VM5tJHm74gCTawivXHCQeLhx9-aiPZ71UPQ8v8aD9Y,20361
|
||||
sqlalchemy/testing/plugin/pytestplugin.py,sha256=fvT5LeUX6kyIxN3y5FZSaaaTBkilGNPi54qGz51fsMM,16189
|
||||
sqlalchemy/testing/profiling.py,sha256=Sm1jEw_H0IOFl_fL8xSvYH5oSOYnRi-jYN1krlR7rJI,8855
|
||||
sqlalchemy/testing/provision.py,sha256=qWmrATrDsGAJUgQgg5gyS7iRxAYvsHY2T_psTvV4GTg,5509
|
||||
sqlalchemy/testing/replay_fixture.py,sha256=W_QZD96t7ichRNvILOjhuoQXTCYnd2usiHBQhPkzUYI,5875
|
||||
sqlalchemy/testing/requirements.py,sha256=YMD5ILDKaYFY2g9pTY_7UwkTneuBpPgiigDMunGt_BQ,32131
|
||||
sqlalchemy/testing/schema.py,sha256=V5Kggty3LB9YDzbLqmSHsc60J7fUXLDnBJnt_ZmXkas,3712
|
||||
sqlalchemy/testing/suite/__init__.py,sha256=SUWU-LR3asH2hN2YsIhlpqxeuo8fpvej3o6nct-L4xU,358
|
||||
sqlalchemy/testing/suite/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_cte.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_ddl.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_dialect.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_insert.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_reflection.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_results.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_select.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_sequence.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_types.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/__pycache__/test_update_delete.cpython-37.pyc,,
|
||||
sqlalchemy/testing/suite/test_cte.py,sha256=VbBzRrNWXk2EkuFAz5f5vFXaR9tU240c63dSY88qpf0,6801
|
||||
sqlalchemy/testing/suite/test_ddl.py,sha256=TGFhoJEy-_NqPb5ypR8x8eYW7Xus323kt4p9DXRsjtk,2896
|
||||
sqlalchemy/testing/suite/test_dialect.py,sha256=LQmHD11UKObwB5bwh4QCJChk501AExe7FHvScOB5QAE,6197
|
||||
sqlalchemy/testing/suite/test_insert.py,sha256=Hiwa4iE-oG4csNG57CieNgN2-hGfHX8xgbMQT3rM0TE,9672
|
||||
sqlalchemy/testing/suite/test_reflection.py,sha256=YhJ7O4MN9R__VOjr0yrNnkudiaSezj493gwQi25d84s,41641
|
||||
sqlalchemy/testing/suite/test_results.py,sha256=wemYY7ZTVisKLbks8p1Maf1HEOLZ9vigIsGoHHc4Cbw,10971
|
||||
sqlalchemy/testing/suite/test_select.py,sha256=r_Whu2VLr6l_9BNp8vYikzOYzbh-V73l_yn-OX98nVc,23049
|
||||
sqlalchemy/testing/suite/test_sequence.py,sha256=oacBvtAqW3Ua3gcqyqnT1U_hpJutEW_EmEbwvf7Xq7E,4661
|
||||
sqlalchemy/testing/suite/test_types.py,sha256=ttLLKd5faoa0Uvr-HKRTvieNhlASaSnwj7c9HuB50jk,37159
|
||||
sqlalchemy/testing/suite/test_update_delete.py,sha256=I2NOhWu7iwKLJzcqM_6sLh3WCE1jmcN8tLwBzvNYLPg,1491
|
||||
sqlalchemy/testing/util.py,sha256=Pn41mDkl_Bb7mCbzGmqA4m1d5LCrpvh8v4C7lUCKvwY,10149
|
||||
sqlalchemy/testing/warnings.py,sha256=m0M3oN0gR7VH7d_VbFZaQu2igcsJDKTJvKRwNdfEwsY,1671
|
||||
sqlalchemy/types.py,sha256=LRIjlg-DVeBMAhVI7iXXY8NhQQDDr2UPKp3ONwyMZhI,3377
|
||||
sqlalchemy/util/__init__.py,sha256=ohFYPWxLu_BxGvDgCLvl7r2CrkB0y3vcN3DnePBsauA,6648
|
||||
sqlalchemy/util/__pycache__/__init__.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/_collections.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/compat.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/deprecations.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/langhelpers.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/queue.cpython-37.pyc,,
|
||||
sqlalchemy/util/__pycache__/topological.cpython-37.pyc,,
|
||||
sqlalchemy/util/_collections.py,sha256=MfX2a2MJ95_cYqGQFDWTuf_y7frdtY-z7LBI261HJWE,29219
|
||||
sqlalchemy/util/compat.py,sha256=LqV8UIGP7-WEmBI7H-sIsxGi1B9XRppxuxJyGoYE4_c,16828
|
||||
sqlalchemy/util/deprecations.py,sha256=odcWi5Ciq7T-kpYbavOjMaK89fuX6BvN4j-zB_Pr8BA,7474
|
||||
sqlalchemy/util/langhelpers.py,sha256=aaV0kbtmiQfRXCYaHgYGITYE01apkoFuJWlwYTO0p5U,50512
|
||||
sqlalchemy/util/queue.py,sha256=QHh_QckIfyisS9q_blxbwamt92JPXKZgt-pf971dsEs,6827
|
||||
sqlalchemy/util/topological.py,sha256=lbXO1ZDDTtYHps_rE7NlEZ3AG773IDLP_7L941DTt6U,2767
|
@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.32.3)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp37-cp37m-linux_armv7l
|
||||
|
@ -1 +0,0 @@
|
||||
sqlalchemy
|
@ -1 +0,0 @@
|
||||
pip
|
@ -1,28 +0,0 @@
|
||||
Copyright 2007 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,127 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Werkzeug
|
||||
Version: 1.0.0
|
||||
Summary: The comprehensive WSGI web application library.
|
||||
Home-page: https://palletsprojects.com/p/werkzeug/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: Pallets
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Documentation, https://werkzeug.palletsprojects.com/
|
||||
Project-URL: Code, https://github.com/pallets/werkzeug
|
||||
Project-URL: Issue tracker, https://github.com/pallets/werkzeug/issues
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
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
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware
|
||||
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
||||
Description-Content-Type: text/x-rst
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pytest ; extra == 'dev'
|
||||
Requires-Dist: coverage ; extra == 'dev'
|
||||
Requires-Dist: tox ; extra == 'dev'
|
||||
Requires-Dist: sphinx ; extra == 'dev'
|
||||
Requires-Dist: pallets-sphinx-themes ; extra == 'dev'
|
||||
Requires-Dist: sphinx-issues ; extra == 'dev'
|
||||
Provides-Extra: watchdog
|
||||
Requires-Dist: watchdog ; extra == 'watchdog'
|
||||
|
||||
Werkzeug
|
||||
========
|
||||
|
||||
*werkzeug* German noun: "tool". Etymology: *werk* ("work"), *zeug* ("stuff")
|
||||
|
||||
Werkzeug is a comprehensive `WSGI`_ web application library. It began as
|
||||
a simple collection of various utilities for WSGI applications and has
|
||||
become one of the most advanced WSGI utility libraries.
|
||||
|
||||
It includes:
|
||||
|
||||
- An interactive debugger that allows inspecting stack traces and
|
||||
source code in the browser with an interactive interpreter for any
|
||||
frame in the stack.
|
||||
- A full-featured request object with objects to interact with
|
||||
headers, query args, form data, files, and cookies.
|
||||
- A response object that can wrap other WSGI applications and handle
|
||||
streaming data.
|
||||
- A routing system for matching URLs to endpoints and generating URLs
|
||||
for endpoints, with an extensible system for capturing variables
|
||||
from URLs.
|
||||
- HTTP utilities to handle entity tags, cache control, dates, user
|
||||
agents, cookies, files, and more.
|
||||
- A threaded WSGI server for use while developing applications
|
||||
locally.
|
||||
- A test client for simulating HTTP requests during testing without
|
||||
requiring running a server.
|
||||
|
||||
Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up
|
||||
to the developer to choose a template engine, database adapter, and even
|
||||
how to handle requests. It can be used to build all sorts of end user
|
||||
applications such as blogs, wikis, or bulletin boards.
|
||||
|
||||
`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while
|
||||
providing more structure and patterns for defining powerful
|
||||
applications.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
pip install -U Werkzeug
|
||||
|
||||
|
||||
A Simple Example
|
||||
----------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from werkzeug.wrappers import Request, Response
|
||||
|
||||
@Request.application
|
||||
def application(request):
|
||||
return Response('Hello, World!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
from werkzeug.serving import run_simple
|
||||
run_simple('localhost', 4000, application)
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- Website: https://palletsprojects.com/p/werkzeug/
|
||||
- Documentation: https://werkzeug.palletsprojects.com/
|
||||
- Releases: https://pypi.org/project/Werkzeug/
|
||||
- Code: https://github.com/pallets/werkzeug
|
||||
- Issue tracker: https://github.com/pallets/werkzeug/issues
|
||||
- Test status: https://dev.azure.com/pallets/werkzeug/_build
|
||||
- Official chat: https://discord.gg/t6rrQZH
|
||||
|
||||
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
|
||||
.. _Flask: https://www.palletsprojects.com/p/flask/
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
@ -1,101 +0,0 @@
|
||||
Werkzeug-1.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Werkzeug-1.0.0.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475
|
||||
Werkzeug-1.0.0.dist-info/METADATA,sha256=PYrtVKBaudcg8XAd-XR_FP0XKeHwh2svMnYDkF3NMEM,4683
|
||||
Werkzeug-1.0.0.dist-info/RECORD,,
|
||||
Werkzeug-1.0.0.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
|
||||
Werkzeug-1.0.0.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9
|
||||
werkzeug/__init__.py,sha256=tuMKcU_g68IyAqFr7KP27w82oHdbHCJo5jsELm56krM,502
|
||||
werkzeug/__pycache__/__init__.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/_compat.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/_internal.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/_reloader.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/datastructures.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/exceptions.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/filesystem.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/formparser.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/http.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/local.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/posixemulation.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/routing.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/security.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/serving.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/test.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/testapp.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/urls.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/useragents.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/utils.cpython-37.pyc,,
|
||||
werkzeug/__pycache__/wsgi.cpython-37.pyc,,
|
||||
werkzeug/_compat.py,sha256=zjufTNrhQ8BgYSGSh-sVu6iW3r3O9WzjE9j-qJobx-g,6671
|
||||
werkzeug/_internal.py,sha256=d_4AqheyS6dHMViwdc0drFrjs67ZzT6Ej2gWf-Z-Iys,14351
|
||||
werkzeug/_reloader.py,sha256=I3mg3oRQ0lLzl06oEoVopN3bN7CtINuuUQdqDcmTnEs,11531
|
||||
werkzeug/datastructures.py,sha256=lgSnQ5E_hMlbKD6_Iq0eT1CBW_CPobVUqhunHqUWrPs,100436
|
||||
werkzeug/debug/__init__.py,sha256=3RtUMc5Y9hYyK11ugHltgkQ9Dt-ViR945Vy_X5NV7zU,17289
|
||||
werkzeug/debug/__pycache__/__init__.cpython-37.pyc,,
|
||||
werkzeug/debug/__pycache__/console.cpython-37.pyc,,
|
||||
werkzeug/debug/__pycache__/repr.cpython-37.pyc,,
|
||||
werkzeug/debug/__pycache__/tbtools.cpython-37.pyc,,
|
||||
werkzeug/debug/console.py,sha256=YHfFF7b4gRfG9aM7_KxwnUBN5nX8mr0OBTPOIMCpyiQ,5461
|
||||
werkzeug/debug/repr.py,sha256=lIwuhbyrMwVe3P_cFqNyqzHL7P93TLKod7lw9clydEw,9621
|
||||
werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673
|
||||
werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507
|
||||
werkzeug/debug/shared/debugger.js,sha256=rOhqZMRfpZnnu6_XCGn6wMWPhtfwRAcyZKksdIxPJas,6400
|
||||
werkzeug/debug/shared/jquery.js,sha256=CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo,88145
|
||||
werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191
|
||||
werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200
|
||||
werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818
|
||||
werkzeug/debug/shared/style.css,sha256=gZ9uhmb5zj3XLuT9RvnMp6jMINgQ-VVBCp-2AZbG3YQ,6604
|
||||
werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220
|
||||
werkzeug/debug/tbtools.py,sha256=2iJ8RURUZUSbopOIehy53LnVJWx47lsHN2V2l6hc7Wc,20363
|
||||
werkzeug/exceptions.py,sha256=UTYSDkmAsH-vt8VSidlEffwqBVNXuT7bRg-_NqgUe8A,25188
|
||||
werkzeug/filesystem.py,sha256=HzKl-j0Hd8Jl66j778UbPTAYNnY6vUZgYLlBZ0e7uw0,2101
|
||||
werkzeug/formparser.py,sha256=Sto0jZid9im9ZVIf56vilCdyX-arK33wSftkYsLCnzo,21788
|
||||
werkzeug/http.py,sha256=YLEcmPFGAwltCLUl-D97l1EEWwLOl_UshuMOXssGm0M,43052
|
||||
werkzeug/local.py,sha256=_Tk7gB238pPWUU7habxFkZF02fiCMRVW6d62YWL1Rh0,14371
|
||||
werkzeug/middleware/__init__.py,sha256=f1SFZo67IlW4k1uqKzNHxYQlsakUS-D6KK_j0e3jjwQ,549
|
||||
werkzeug/middleware/__pycache__/__init__.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/dispatcher.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/http_proxy.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/lint.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/profiler.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/proxy_fix.cpython-37.pyc,,
|
||||
werkzeug/middleware/__pycache__/shared_data.cpython-37.pyc,,
|
||||
werkzeug/middleware/dispatcher.py,sha256=_-KoMzHtcISHS7ouWKAOraqlCLprdh83YOAn_8DjLp8,2240
|
||||
werkzeug/middleware/http_proxy.py,sha256=lRjTdMmghHiZuZrS7_UJ3gZc-vlFizhBbFZ-XZPLwIA,7117
|
||||
werkzeug/middleware/lint.py,sha256=ItTwuWJnflF8xMT1uqU_Ty1ryhux-CjeUfskqaUpxsw,12967
|
||||
werkzeug/middleware/profiler.py,sha256=8B_s23d6BGrU_q54gJsm6kcCbOJbTSqrXCsioHON0Xs,4471
|
||||
werkzeug/middleware/proxy_fix.py,sha256=K5oZ3DPXOzdZi0Xba5zW7ClPOxgUuqXHQHvY2-AWCGw,6431
|
||||
werkzeug/middleware/shared_data.py,sha256=2V4lLqK9CZLFcxtOAjZE7ZVY4SIU_cKLdKKaMmJPO3o,9581
|
||||
werkzeug/posixemulation.py,sha256=gSSiv1SCmOyzOM_nq1ZaZCtxP__C5MeDJl_4yXJmi4Q,3541
|
||||
werkzeug/routing.py,sha256=zF5Px2KLYThv634WBZRK3jiOPUQIcRe1iGz0R0eaSzM,79014
|
||||
werkzeug/security.py,sha256=81149MplFq7-hD4RK4sKp9kzXXejjV9D4lWBzaRyeQ8,8106
|
||||
werkzeug/serving.py,sha256=YvTqvurA-Mnj8mkqRe2kBdVr2ap4ibCq1ByQjOA6g1w,38694
|
||||
werkzeug/test.py,sha256=GJ9kxTMSJ-nB7kfGtxuROr9JGmXxDRev-2U1SkeUJGE,39564
|
||||
werkzeug/testapp.py,sha256=bHekqMsqRfVxwgFbvOMem-DYa_sdB7R47yUXpt1RUTo,9329
|
||||
werkzeug/urls.py,sha256=T8-hV_1vwhu6xhX93FwsHteK-W-kIE2orj5WoMf-WFw,39322
|
||||
werkzeug/useragents.py,sha256=UOckz1Ts8buNA_KJvVOT6iqNP5EFl3P5JqlpwiQUI-w,5451
|
||||
werkzeug/utils.py,sha256=hrVK4u_wi8z9viBO9bgOLlm1aaIvCpn-p2d1FeZQDEo,25251
|
||||
werkzeug/wrappers/__init__.py,sha256=S4VioKAmF_av9Ec9zQvG71X1EOkYfPx1TYck9jyDiyY,1384
|
||||
werkzeug/wrappers/__pycache__/__init__.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/accept.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/auth.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/base_request.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/base_response.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/common_descriptors.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/cors.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/etag.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/json.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/request.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/response.cpython-37.pyc,,
|
||||
werkzeug/wrappers/__pycache__/user_agent.cpython-37.pyc,,
|
||||
werkzeug/wrappers/accept.py,sha256=TIvjUc0g73fhTWX54wg_D9NNzKvpnG1X8u1w26tK1o8,1760
|
||||
werkzeug/wrappers/auth.py,sha256=Pmn6iaGHBrUyHbJpW0lZhO_q9RVoAa5QalaTqcavdAI,1158
|
||||
werkzeug/wrappers/base_request.py,sha256=4TuGlKWeKQdlq4eU94hJYcXSfWo8Rk7CS1Ef5lJ3ZM0,26012
|
||||
werkzeug/wrappers/base_response.py,sha256=JTxJZ8o-IBetpoWJqt2HFwPaNWNDAlM3_GXJe1Whw80,27784
|
||||
werkzeug/wrappers/common_descriptors.py,sha256=X2Ktd5zUWsmcd4ciaF62Dd8Lru9pLGP_XDUNukc8cXs,12829
|
||||
werkzeug/wrappers/cors.py,sha256=hwbXEVjiqDT4MybRgstMYQw4NqgiXEiQ9wmlC3sqNA8,3512
|
||||
werkzeug/wrappers/etag.py,sha256=XMXtyfByBsOjxwaX8U7ZtUY7JXkbQLP45oXZ0qkyTNs,12217
|
||||
werkzeug/wrappers/json.py,sha256=HvK_A4NpO0sLqgb10sTJcoZydYOwyNiPCJPV7SVgcgE,4343
|
||||
werkzeug/wrappers/request.py,sha256=QbHGqDpGPN684pnOPEokwkPESfm-NnfYM7ydOMxW_NI,1514
|
||||
werkzeug/wrappers/response.py,sha256=Oqv8TMG_dnOKTq_V30ddgkO5B7IJhkVPODvm7cbhZ3c,2524
|
||||
werkzeug/wrappers/user_agent.py,sha256=YJb-vr12cujG7sQMG9V89VsJa-03SWSenhg1W4cT0EY,435
|
||||
werkzeug/wsgi.py,sha256=ZGk85NzRyQTzkYis-xl8V9ydJgfClBdStvhzDzER2mw,34367
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1 +0,0 @@
|
||||
werkzeug
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
pip
|
@ -1,19 +0,0 @@
|
||||
Copyright 2009-2020 Michael Bayer.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,138 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: alembic
|
||||
Version: 1.4.2
|
||||
Summary: A database migration tool for SQLAlchemy.
|
||||
Home-page: https://alembic.sqlalchemy.org
|
||||
Author: Mike Bayer
|
||||
Author-email: mike@zzzcomputing.com
|
||||
License: MIT
|
||||
Project-URL: Issue Tracker, https://github.com/sqlalchemy/alembic/
|
||||
Keywords: SQLAlchemy migrations
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
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
|
||||
Classifier: Topic :: Database :: Front-Ends
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Requires-Dist: SQLAlchemy (>=1.1.0)
|
||||
Requires-Dist: Mako
|
||||
Requires-Dist: python-editor (>=0.3)
|
||||
Requires-Dist: python-dateutil
|
||||
|
||||
Alembic is a database migrations tool written by the author
|
||||
of `SQLAlchemy <http://www.sqlalchemy.org>`_. A migrations tool
|
||||
offers the following functionality:
|
||||
|
||||
* Can emit ALTER statements to a database in order to change
|
||||
the structure of tables and other constructs
|
||||
* Provides a system whereby "migration scripts" may be constructed;
|
||||
each script indicates a particular series of steps that can "upgrade" a
|
||||
target database to a new version, and optionally a series of steps that can
|
||||
"downgrade" similarly, doing the same steps in reverse.
|
||||
* Allows the scripts to execute in some sequential manner.
|
||||
|
||||
The goals of Alembic are:
|
||||
|
||||
* Very open ended and transparent configuration and operation. A new
|
||||
Alembic environment is generated from a set of templates which is selected
|
||||
among a set of options when setup first occurs. The templates then deposit a
|
||||
series of scripts that define fully how database connectivity is established
|
||||
and how migration scripts are invoked; the migration scripts themselves are
|
||||
generated from a template within that series of scripts. The scripts can
|
||||
then be further customized to define exactly how databases will be
|
||||
interacted with and what structure new migration files should take.
|
||||
* Full support for transactional DDL. The default scripts ensure that all
|
||||
migrations occur within a transaction - for those databases which support
|
||||
this (Postgresql, Microsoft SQL Server), migrations can be tested with no
|
||||
need to manually undo changes upon failure.
|
||||
* Minimalist script construction. Basic operations like renaming
|
||||
tables/columns, adding/removing columns, changing column attributes can be
|
||||
performed through one line commands like alter_column(), rename_table(),
|
||||
add_constraint(). There is no need to recreate full SQLAlchemy Table
|
||||
structures for simple operations like these - the functions themselves
|
||||
generate minimalist schema structures behind the scenes to achieve the given
|
||||
DDL sequence.
|
||||
* "auto generation" of migrations. While real world migrations are far more
|
||||
complex than what can be automatically determined, Alembic can still
|
||||
eliminate the initial grunt work in generating new migration directives
|
||||
from an altered schema. The ``--autogenerate`` feature will inspect the
|
||||
current status of a database using SQLAlchemy's schema inspection
|
||||
capabilities, compare it to the current state of the database model as
|
||||
specified in Python, and generate a series of "candidate" migrations,
|
||||
rendering them into a new migration script as Python directives. The
|
||||
developer then edits the new file, adding additional directives and data
|
||||
migrations as needed, to produce a finished migration. Table and column
|
||||
level changes can be detected, with constraints and indexes to follow as
|
||||
well.
|
||||
* Full support for migrations generated as SQL scripts. Those of us who
|
||||
work in corporate environments know that direct access to DDL commands on a
|
||||
production database is a rare privilege, and DBAs want textual SQL scripts.
|
||||
Alembic's usage model and commands are oriented towards being able to run a
|
||||
series of migrations into a textual output file as easily as it runs them
|
||||
directly to a database. Care must be taken in this mode to not invoke other
|
||||
operations that rely upon in-memory SELECTs of rows - Alembic tries to
|
||||
provide helper constructs like bulk_insert() to help with data-oriented
|
||||
operations that are compatible with script-based DDL.
|
||||
* Non-linear, dependency-graph versioning. Scripts are given UUID
|
||||
identifiers similarly to a DVCS, and the linkage of one script to the next
|
||||
is achieved via human-editable markers within the scripts themselves.
|
||||
The structure of a set of migration files is considered as a
|
||||
directed-acyclic graph, meaning any migration file can be dependent
|
||||
on any other arbitrary set of migration files, or none at
|
||||
all. Through this open-ended system, migration files can be organized
|
||||
into branches, multiple roots, and mergepoints, without restriction.
|
||||
Commands are provided to produce new branches, roots, and merges of
|
||||
branches automatically.
|
||||
* Provide a library of ALTER constructs that can be used by any SQLAlchemy
|
||||
application. The DDL constructs build upon SQLAlchemy's own DDLElement base
|
||||
and can be used standalone by any application or script.
|
||||
* At long last, bring SQLite and its inablity to ALTER things into the fold,
|
||||
but in such a way that SQLite's very special workflow needs are accommodated
|
||||
in an explicit way that makes the most of a bad situation, through the
|
||||
concept of a "batch" migration, where multiple changes to a table can
|
||||
be batched together to form a series of instructions for a single, subsequent
|
||||
"move-and-copy" workflow. You can even use "move-and-copy" workflow for
|
||||
other databases, if you want to recreate a table in the background
|
||||
on a busy system.
|
||||
|
||||
Documentation and status of Alembic is at https://alembic.sqlalchemy.org/
|
||||
|
||||
The SQLAlchemy Project
|
||||
======================
|
||||
|
||||
Alembic is part of the `SQLAlchemy Project <https://www.sqlalchemy.org>`_ and
|
||||
adheres to the same standards and conventions as the core project.
|
||||
|
||||
Development / Bug reporting / Pull requests
|
||||
___________________________________________
|
||||
|
||||
Please refer to the
|
||||
`SQLAlchemy Community Guide <https://www.sqlalchemy.org/develop.html>`_ for
|
||||
guidelines on coding and participating in this project.
|
||||
|
||||
Code of Conduct
|
||||
_______________
|
||||
|
||||
Above all, SQLAlchemy places great emphasis on polite, thoughtful, and
|
||||
constructive communication between users and developers.
|
||||
Please see our current Code of Conduct at
|
||||
`Code of Conduct <https://www.sqlalchemy.org/codeofconduct.html>`_.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Alembic is distributed under the `MIT license
|
||||
<https://opensource.org/licenses/MIT>`_.
|
||||
|
||||
|
@ -1,123 +0,0 @@
|
||||
../../../bin/alembic,sha256=VhYgSnMwRngw1J3SuVvszUPA9Z7S5ggue9MFG8vbWrY,237
|
||||
alembic-1.4.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
alembic-1.4.2.dist-info/LICENSE,sha256=vEAGUIuUWeKAHsWgwcUTyJRHJWjUmGO9MZ84k2KBhFE,1058
|
||||
alembic-1.4.2.dist-info/METADATA,sha256=LaCIAVi-eI4fLOHSaX9v0PJpFyBLdDX2DXPcLS0v9iM,7011
|
||||
alembic-1.4.2.dist-info/RECORD,,
|
||||
alembic-1.4.2.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
|
||||
alembic-1.4.2.dist-info/entry_points.txt,sha256=jOSnN_2fhU8xzDQ50rdNr425J8kf_exuY8GrAo1daz8,49
|
||||
alembic-1.4.2.dist-info/top_level.txt,sha256=FwKWd5VsPFC8iQjpu1u9Cn-JnK3-V1RhUCmWqz1cl-s,8
|
||||
alembic/__init__.py,sha256=DzXW72ndu6EzMX0RlBznxpIQI1TfpxLm7fo6ah6yiKM,249
|
||||
alembic/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/__pycache__/command.cpython-37.pyc,,
|
||||
alembic/__pycache__/config.cpython-37.pyc,,
|
||||
alembic/__pycache__/context.cpython-37.pyc,,
|
||||
alembic/__pycache__/op.cpython-37.pyc,,
|
||||
alembic/autogenerate/__init__.py,sha256=98WZvBQ3k-cfpa1GsVFEq0Kqmzl1-UPYCtau9urpsIQ,431
|
||||
alembic/autogenerate/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/autogenerate/__pycache__/api.cpython-37.pyc,,
|
||||
alembic/autogenerate/__pycache__/compare.cpython-37.pyc,,
|
||||
alembic/autogenerate/__pycache__/render.cpython-37.pyc,,
|
||||
alembic/autogenerate/__pycache__/rewriter.cpython-37.pyc,,
|
||||
alembic/autogenerate/api.py,sha256=Bg1pnUM9qpSGk6sxGMaYCSME8RaRHz3K4mb0Qar4o6A,17027
|
||||
alembic/autogenerate/compare.py,sha256=cRBt7ZBFRiRjhvo0pA3XvuUw0YOdmZwy_2k_pJoZaL0,39009
|
||||
alembic/autogenerate/render.py,sha256=m8vE8w1XKI9aoaq6cmbzO0pWh2wgnKGY5E6M0Y8YYq4,29117
|
||||
alembic/autogenerate/rewriter.py,sha256=rERJzPZtzzs9rHA6XLz8M5M9PVEHFBrMZ2YZBO09f6E,5721
|
||||
alembic/command.py,sha256=C_nGc-Ay0mkKQA3Po4BgPygUS8Po87kap6-YRLgsdLM,18129
|
||||
alembic/config.py,sha256=cTJTxr1buPkVLap32k-mnu8ccd4s5so0dL4YKaZVi5w,19865
|
||||
alembic/context.py,sha256=hK1AJOQXJ29Bhn276GYcosxeG7pC5aZRT5E8c4bMJ4Q,195
|
||||
alembic/ddl/__init__.py,sha256=7cwkSz69tWKVbUxbHpE0SDOYUgbxSBkVIHHTyJ1O7V8,185
|
||||
alembic/ddl/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/base.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/impl.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/mssql.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/mysql.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/oracle.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/postgresql.cpython-37.pyc,,
|
||||
alembic/ddl/__pycache__/sqlite.cpython-37.pyc,,
|
||||
alembic/ddl/base.py,sha256=tjjyvaxbgY2q5POm8MEEqGMIdQHaUjBS3dAkN5qVFrQ,6812
|
||||
alembic/ddl/impl.py,sha256=44AQywPLQl3cKS7bUQLw1PpDX05sIKizQHNpk-FpFpg,16557
|
||||
alembic/ddl/mssql.py,sha256=7iSSBE2izonS7GWKbB2qd0OprD35oBRSIEJIxY-iRyc,9361
|
||||
alembic/ddl/mysql.py,sha256=VPU7BoxUFh-kZcxFkHsPO17On-ijiQsvsiEQg3Ckj34,13911
|
||||
alembic/ddl/oracle.py,sha256=RIaGxJV0Gp58thdrXW9UqH-4jYke-RKmHj7nGc9396A,3810
|
||||
alembic/ddl/postgresql.py,sha256=bKzEZOGYJ8Lcd5bob_HMNlo6xnkZCosQglC2iGIZFwM,17602
|
||||
alembic/ddl/sqlite.py,sha256=w1pcH1CZgDfDIu9TJAnZezF8TPpuY1lDEttJ4_dyJmU,4700
|
||||
alembic/op.py,sha256=flHtcsVqOD-ZgZKK2pv-CJ5Cwh-KJ7puMUNXzishxLw,167
|
||||
alembic/operations/__init__.py,sha256=nJbmMAwapU2py4fJ4GUBanBp-EMXhDyMngb717NIHM8,192
|
||||
alembic/operations/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/operations/__pycache__/base.cpython-37.pyc,,
|
||||
alembic/operations/__pycache__/batch.cpython-37.pyc,,
|
||||
alembic/operations/__pycache__/ops.cpython-37.pyc,,
|
||||
alembic/operations/__pycache__/schemaobj.cpython-37.pyc,,
|
||||
alembic/operations/__pycache__/toimpl.cpython-37.pyc,,
|
||||
alembic/operations/base.py,sha256=6C9hWmpdYfVMnCzV_1AqUvtZ-Ixfx_5u8mBw2gxjNdM,17999
|
||||
alembic/operations/batch.py,sha256=hbbMe5bYdM6G2f9b_8AUlJkuKccFUbGZcLrVDp8n8LM,19357
|
||||
alembic/operations/ops.py,sha256=LYLcaz_dVGmhYhUl7wJ3FLU8SD_Af-rzkJbiM-fS0JY,83044
|
||||
alembic/operations/schemaobj.py,sha256=hFUtUzV-kSEq9TnXqH6IygM-aCcB5VjIpUm0kAKYGE4,5736
|
||||
alembic/operations/toimpl.py,sha256=p4CuVYHKeJiUMboY_uxG1_A8lXCTiEjjRCKXoCuNr1M,5716
|
||||
alembic/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
alembic/runtime/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/runtime/__pycache__/environment.cpython-37.pyc,,
|
||||
alembic/runtime/__pycache__/migration.cpython-37.pyc,,
|
||||
alembic/runtime/environment.py,sha256=l1EgAiKX9kO7mam9wrgpQ90X1qGWCuC4t3xOCfYN7bU,37862
|
||||
alembic/runtime/migration.py,sha256=wHtXMMrHV76agAVWVip3g2wlUfo5bBbgDMN3ak7NfqE,42389
|
||||
alembic/script/__init__.py,sha256=SxmoPlnSDLFW_9p-OTG-yaev76Ok7TiyN6u2TAKczkU,116
|
||||
alembic/script/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/script/__pycache__/base.cpython-37.pyc,,
|
||||
alembic/script/__pycache__/revision.cpython-37.pyc,,
|
||||
alembic/script/__pycache__/write_hooks.cpython-37.pyc,,
|
||||
alembic/script/base.py,sha256=WdY4-7RottWuwv07AcOB0xZMpcMWfy7isq6kqmRlpcI,31774
|
||||
alembic/script/revision.py,sha256=v_eTBexwhZJYUrlSh_MH97fXBWh1yZBcO25ganPQLLY,34453
|
||||
alembic/script/write_hooks.py,sha256=0heAelcqI2n4WW440Mz1cqPkHUNvfuS-meMzpiMBDd4,2768
|
||||
alembic/templates/generic/README,sha256=MVlc9TYmr57RbhXET6QxgyCcwWP7w-vLkEsirENqiIQ,38
|
||||
alembic/templates/generic/__pycache__/env.cpython-37.pyc,,
|
||||
alembic/templates/generic/alembic.ini.mako,sha256=wexLbI6y199q77PCKJADZAmUIXUhGBhlYUMt-hzzwQ0,2044
|
||||
alembic/templates/generic/env.py,sha256=LN06WkE0nj1RGL--SbzYfx4DRopSl5g2Ihu6knUJMZQ,2039
|
||||
alembic/templates/generic/script.py.mako,sha256=8_xgA-gm_OhehnO7CiIijWgnm00ZlszEHtIHrAYFJl0,494
|
||||
alembic/templates/multidb/README,sha256=c7CNHkVvVSJsGZ75Qlcuo1nXKQITDu0W3hSULyz1pWg,41
|
||||
alembic/templates/multidb/__pycache__/env.cpython-37.pyc,,
|
||||
alembic/templates/multidb/alembic.ini.mako,sha256=1ci-FAmvH99PCOcWwq-D8fWs4Hx2XxMQPr-2VWe2BQI,2138
|
||||
alembic/templates/multidb/env.py,sha256=kDOOlbzDLc1nhFbsKJ-bclZ0mpEjLMeJdS9Gu_H5zWo,4162
|
||||
alembic/templates/multidb/script.py.mako,sha256=k09J7yYXfXFyedV6D5VgJzuPQxPnYKxID0huIabH46w,923
|
||||
alembic/templates/pylons/README,sha256=gr4MQnn_ScvV_kasPpXgo6ntAtcIWmOlga9vURbgUwI,59
|
||||
alembic/templates/pylons/__pycache__/env.cpython-37.pyc,,
|
||||
alembic/templates/pylons/alembic.ini.mako,sha256=i-NMyRa8jZoX89ra-pDHdXQzsB3q7YvQRDFTaz6z2Jw,1523
|
||||
alembic/templates/pylons/env.py,sha256=VZyuB0IllLLu1i8jec_-Wj5Ry7D0KgOr8cSISLYFK_8,2245
|
||||
alembic/templates/pylons/script.py.mako,sha256=8_xgA-gm_OhehnO7CiIijWgnm00ZlszEHtIHrAYFJl0,494
|
||||
alembic/testing/__init__.py,sha256=sWNfwWdj_gDR2nk08lA8zZtsqLbfYMPT25W4JJu-gIY,1065
|
||||
alembic/testing/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/assertions.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/env.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/exclusions.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/fixture_functions.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/fixtures.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/requirements.cpython-37.pyc,,
|
||||
alembic/testing/__pycache__/util.cpython-37.pyc,,
|
||||
alembic/testing/assertions.py,sha256=zgQkrDYUPFixItL3hWr0OmNMDZyKY0lZUTsy9xQ1nzc,3292
|
||||
alembic/testing/env.py,sha256=A--5nnemVi8mmimkNxF_d2dqBjGl2IOVRlUH3JJvWZI,10250
|
||||
alembic/testing/exclusions.py,sha256=ppAglvtwGg442E0F6TOmuuTgLT_NkWs3mbQ3Zv8uPeU,14289
|
||||
alembic/testing/fixture_functions.py,sha256=FOhaHKaDtNlItGIyOG6uVGB2pj6Aoi4Qlr9H-xPPF1Y,2952
|
||||
alembic/testing/fixtures.py,sha256=Q5XxgJAeWXEhCcBmaYRndTG89ZZj4jo0Qu8dn1TMTRM,7869
|
||||
alembic/testing/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
alembic/testing/plugin/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/testing/plugin/__pycache__/bootstrap.cpython-37.pyc,,
|
||||
alembic/testing/plugin/__pycache__/plugin_base.cpython-37.pyc,,
|
||||
alembic/testing/plugin/__pycache__/pytestplugin.cpython-37.pyc,,
|
||||
alembic/testing/plugin/bootstrap.py,sha256=5sN6F4OJ3UUNVUeNBzY-MjN_r3tOH5NrGx4maJuRC9U,857
|
||||
alembic/testing/plugin/plugin_base.py,sha256=Hcs-ODRbzUSFvtVQ7eiL_d6bXbGeLut0-Y2XQAEwIMw,3080
|
||||
alembic/testing/plugin/pytestplugin.py,sha256=1MF5hq73_Xiu97sVMuuS-uex0mSvvhtFZh_Io6QJnkM,7529
|
||||
alembic/testing/requirements.py,sha256=dZUI-PhV2TOPuxFZQEUAAivXynitjWgCkJIipjGz-1w,4136
|
||||
alembic/testing/util.py,sha256=sA_4b_EQ0gfz2BozAw-eNYanJYBQh8oO66iLMVIs7tw,2577
|
||||
alembic/util/__init__.py,sha256=HCPvV0cpyhdIgyVRKDuYIP_S9EJE0adE97d92zW81p8,1473
|
||||
alembic/util/__pycache__/__init__.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/compat.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/exc.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/langhelpers.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/messaging.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/pyfiles.cpython-37.pyc,,
|
||||
alembic/util/__pycache__/sqla_compat.cpython-37.pyc,,
|
||||
alembic/util/compat.py,sha256=knJEgDHsBcUDzotYEvg23V0Gj2ZvS8i0fj8IpG4kBeM,10563
|
||||
alembic/util/exc.py,sha256=GBd-Fw-pvtsUNg6wrub7yhY2venv1MD1eMuJZebJiMY,40
|
||||
alembic/util/langhelpers.py,sha256=BXkBYZQxh96Jb2B3GKlZvnhJ0bBVRujatLosBlVeZmk,9246
|
||||
alembic/util/messaging.py,sha256=r8nAmwzbvGmO8Rtdxq-a6EJdEJEG1zP4l0eUEMTyItM,2633
|
||||
alembic/util/pyfiles.py,sha256=mpcMVT6fVcTSLFxB2fWD6RSExMW6jkv4p5FWDDF7yJs,3028
|
||||
alembic/util/sqla_compat.py,sha256=czTo3m1Mrs51BQOQCcKhBhsh9ATIZMplfjqAjoWFp1g,8718
|
@ -1,6 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -1,3 +0,0 @@
|
||||
[console_scripts]
|
||||
alembic = alembic.config:main
|
||||
|
@ -1 +0,0 @@
|
||||
alembic
|
@ -1,11 +0,0 @@
|
||||
import sys
|
||||
|
||||
from . import context # noqa
|
||||
from . import op # noqa
|
||||
from .runtime import environment
|
||||
from .runtime import migration
|
||||
|
||||
__version__ = "1.4.2"
|
||||
|
||||
sys.modules["alembic.migration"] = migration
|
||||
sys.modules["alembic.environment"] = environment
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,10 +0,0 @@
|
||||
from .api import _render_migration_diffs # noqa
|
||||
from .api import compare_metadata # noqa
|
||||
from .api import produce_migrations # noqa
|
||||
from .api import render_python_code # noqa
|
||||
from .api import RevisionContext # noqa
|
||||
from .compare import _produce_net_changes # noqa
|
||||
from .compare import comparators # noqa
|
||||
from .render import render_op_text # noqa
|
||||
from .render import renderers # noqa
|
||||
from .rewriter import Rewriter # noqa
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,513 +0,0 @@
|
||||
"""Provide the 'autogenerate' feature which can produce migration operations
|
||||
automatically."""
|
||||
|
||||
import contextlib
|
||||
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from . import compare
|
||||
from . import render
|
||||
from .. import util
|
||||
from ..operations import ops
|
||||
|
||||
|
||||
def compare_metadata(context, metadata):
|
||||
"""Compare a database schema to that given in a
|
||||
:class:`~sqlalchemy.schema.MetaData` instance.
|
||||
|
||||
The database connection is presented in the context
|
||||
of a :class:`.MigrationContext` object, which
|
||||
provides database connectivity as well as optional
|
||||
comparison functions to use for datatypes and
|
||||
server defaults - see the "autogenerate" arguments
|
||||
at :meth:`.EnvironmentContext.configure`
|
||||
for details on these.
|
||||
|
||||
The return format is a list of "diff" directives,
|
||||
each representing individual differences::
|
||||
|
||||
from alembic.migration import MigrationContext
|
||||
from alembic.autogenerate import compare_metadata
|
||||
from sqlalchemy.schema import SchemaItem
|
||||
from sqlalchemy.types import TypeEngine
|
||||
from sqlalchemy import (create_engine, MetaData, Column,
|
||||
Integer, String, Table)
|
||||
import pprint
|
||||
|
||||
engine = create_engine("sqlite://")
|
||||
|
||||
engine.execute('''
|
||||
create table foo (
|
||||
id integer not null primary key,
|
||||
old_data varchar,
|
||||
x integer
|
||||
)''')
|
||||
|
||||
engine.execute('''
|
||||
create table bar (
|
||||
data varchar
|
||||
)''')
|
||||
|
||||
metadata = MetaData()
|
||||
Table('foo', metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('data', Integer),
|
||||
Column('x', Integer, nullable=False)
|
||||
)
|
||||
Table('bat', metadata,
|
||||
Column('info', String)
|
||||
)
|
||||
|
||||
mc = MigrationContext.configure(engine.connect())
|
||||
|
||||
diff = compare_metadata(mc, metadata)
|
||||
pprint.pprint(diff, indent=2, width=20)
|
||||
|
||||
Output::
|
||||
|
||||
[ ( 'add_table',
|
||||
Table('bat', MetaData(bind=None),
|
||||
Column('info', String(), table=<bat>), schema=None)),
|
||||
( 'remove_table',
|
||||
Table(u'bar', MetaData(bind=None),
|
||||
Column(u'data', VARCHAR(), table=<bar>), schema=None)),
|
||||
( 'add_column',
|
||||
None,
|
||||
'foo',
|
||||
Column('data', Integer(), table=<foo>)),
|
||||
( 'remove_column',
|
||||
None,
|
||||
'foo',
|
||||
Column(u'old_data', VARCHAR(), table=None)),
|
||||
[ ( 'modify_nullable',
|
||||
None,
|
||||
'foo',
|
||||
u'x',
|
||||
{ 'existing_server_default': None,
|
||||
'existing_type': INTEGER()},
|
||||
True,
|
||||
False)]]
|
||||
|
||||
|
||||
:param context: a :class:`.MigrationContext`
|
||||
instance.
|
||||
:param metadata: a :class:`~sqlalchemy.schema.MetaData`
|
||||
instance.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:func:`.produce_migrations` - produces a :class:`.MigrationScript`
|
||||
structure based on metadata comparison.
|
||||
|
||||
"""
|
||||
|
||||
migration_script = produce_migrations(context, metadata)
|
||||
return migration_script.upgrade_ops.as_diffs()
|
||||
|
||||
|
||||
def produce_migrations(context, metadata):
|
||||
"""Produce a :class:`.MigrationScript` structure based on schema
|
||||
comparison.
|
||||
|
||||
This function does essentially what :func:`.compare_metadata` does,
|
||||
but then runs the resulting list of diffs to produce the full
|
||||
:class:`.MigrationScript` object. For an example of what this looks like,
|
||||
see the example in :ref:`customizing_revision`.
|
||||
|
||||
.. versionadded:: 0.8.0
|
||||
|
||||
.. seealso::
|
||||
|
||||
:func:`.compare_metadata` - returns more fundamental "diff"
|
||||
data from comparing a schema.
|
||||
|
||||
"""
|
||||
|
||||
autogen_context = AutogenContext(context, metadata=metadata)
|
||||
|
||||
migration_script = ops.MigrationScript(
|
||||
rev_id=None,
|
||||
upgrade_ops=ops.UpgradeOps([]),
|
||||
downgrade_ops=ops.DowngradeOps([]),
|
||||
)
|
||||
|
||||
compare._populate_migration_script(autogen_context, migration_script)
|
||||
|
||||
return migration_script
|
||||
|
||||
|
||||
def render_python_code(
|
||||
up_or_down_op,
|
||||
sqlalchemy_module_prefix="sa.",
|
||||
alembic_module_prefix="op.",
|
||||
render_as_batch=False,
|
||||
imports=(),
|
||||
render_item=None,
|
||||
migration_context=None,
|
||||
):
|
||||
"""Render Python code given an :class:`.UpgradeOps` or
|
||||
:class:`.DowngradeOps` object.
|
||||
|
||||
This is a convenience function that can be used to test the
|
||||
autogenerate output of a user-defined :class:`.MigrationScript` structure.
|
||||
|
||||
"""
|
||||
opts = {
|
||||
"sqlalchemy_module_prefix": sqlalchemy_module_prefix,
|
||||
"alembic_module_prefix": alembic_module_prefix,
|
||||
"render_item": render_item,
|
||||
"render_as_batch": render_as_batch,
|
||||
}
|
||||
|
||||
if migration_context is None:
|
||||
from ..runtime.migration import MigrationContext
|
||||
from sqlalchemy.engine.default import DefaultDialect
|
||||
|
||||
migration_context = MigrationContext.configure(
|
||||
dialect=DefaultDialect()
|
||||
)
|
||||
|
||||
autogen_context = AutogenContext(migration_context, opts=opts)
|
||||
autogen_context.imports = set(imports)
|
||||
return render._indent(
|
||||
render._render_cmd_body(up_or_down_op, autogen_context)
|
||||
)
|
||||
|
||||
|
||||
def _render_migration_diffs(context, template_args):
|
||||
"""legacy, used by test_autogen_composition at the moment"""
|
||||
|
||||
autogen_context = AutogenContext(context)
|
||||
|
||||
upgrade_ops = ops.UpgradeOps([])
|
||||
compare._produce_net_changes(autogen_context, upgrade_ops)
|
||||
|
||||
migration_script = ops.MigrationScript(
|
||||
rev_id=None,
|
||||
upgrade_ops=upgrade_ops,
|
||||
downgrade_ops=upgrade_ops.reverse(),
|
||||
)
|
||||
|
||||
render._render_python_into_templatevars(
|
||||
autogen_context, migration_script, template_args
|
||||
)
|
||||
|
||||
|
||||
class AutogenContext(object):
|
||||
"""Maintains configuration and state that's specific to an
|
||||
autogenerate operation."""
|
||||
|
||||
metadata = None
|
||||
"""The :class:`~sqlalchemy.schema.MetaData` object
|
||||
representing the destination.
|
||||
|
||||
This object is the one that is passed within ``env.py``
|
||||
to the :paramref:`.EnvironmentContext.configure.target_metadata`
|
||||
parameter. It represents the structure of :class:`.Table` and other
|
||||
objects as stated in the current database model, and represents the
|
||||
destination structure for the database being examined.
|
||||
|
||||
While the :class:`~sqlalchemy.schema.MetaData` object is primarily
|
||||
known as a collection of :class:`~sqlalchemy.schema.Table` objects,
|
||||
it also has an :attr:`~sqlalchemy.schema.MetaData.info` dictionary
|
||||
that may be used by end-user schemes to store additional schema-level
|
||||
objects that are to be compared in custom autogeneration schemes.
|
||||
|
||||
"""
|
||||
|
||||
connection = None
|
||||
"""The :class:`~sqlalchemy.engine.base.Connection` object currently
|
||||
connected to the database backend being compared.
|
||||
|
||||
This is obtained from the :attr:`.MigrationContext.bind` and is
|
||||
utimately set up in the ``env.py`` script.
|
||||
|
||||
"""
|
||||
|
||||
dialect = None
|
||||
"""The :class:`~sqlalchemy.engine.Dialect` object currently in use.
|
||||
|
||||
This is normally obtained from the
|
||||
:attr:`~sqlalchemy.engine.base.Connection.dialect` attribute.
|
||||
|
||||
"""
|
||||
|
||||
imports = None
|
||||
"""A ``set()`` which contains string Python import directives.
|
||||
|
||||
The directives are to be rendered into the ``${imports}`` section
|
||||
of a script template. The set is normally empty and can be modified
|
||||
within hooks such as the
|
||||
:paramref:`.EnvironmentContext.configure.render_item` hook.
|
||||
|
||||
.. versionadded:: 0.8.3
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`autogen_render_types`
|
||||
|
||||
"""
|
||||
|
||||
migration_context = None
|
||||
"""The :class:`.MigrationContext` established by the ``env.py`` script."""
|
||||
|
||||
def __init__(
|
||||
self, migration_context, metadata=None, opts=None, autogenerate=True
|
||||
):
|
||||
|
||||
if (
|
||||
autogenerate
|
||||
and migration_context is not None
|
||||
and migration_context.as_sql
|
||||
):
|
||||
raise util.CommandError(
|
||||
"autogenerate can't use as_sql=True as it prevents querying "
|
||||
"the database for schema information"
|
||||
)
|
||||
|
||||
if opts is None:
|
||||
opts = migration_context.opts
|
||||
|
||||
self.metadata = metadata = (
|
||||
opts.get("target_metadata", None) if metadata is None else metadata
|
||||
)
|
||||
|
||||
if (
|
||||
autogenerate
|
||||
and metadata is None
|
||||
and migration_context is not None
|
||||
and migration_context.script is not None
|
||||
):
|
||||
raise util.CommandError(
|
||||
"Can't proceed with --autogenerate option; environment "
|
||||
"script %s does not provide "
|
||||
"a MetaData object or sequence of objects to the context."
|
||||
% (migration_context.script.env_py_location)
|
||||
)
|
||||
|
||||
include_symbol = opts.get("include_symbol", None)
|
||||
include_object = opts.get("include_object", None)
|
||||
|
||||
object_filters = []
|
||||
if include_symbol:
|
||||
|
||||
def include_symbol_filter(
|
||||
object_, name, type_, reflected, compare_to
|
||||
):
|
||||
if type_ == "table":
|
||||
return include_symbol(name, object_.schema)
|
||||
else:
|
||||
return True
|
||||
|
||||
object_filters.append(include_symbol_filter)
|
||||
if include_object:
|
||||
object_filters.append(include_object)
|
||||
|
||||
self._object_filters = object_filters
|
||||
|
||||
self.migration_context = migration_context
|
||||
if self.migration_context is not None:
|
||||
self.connection = self.migration_context.bind
|
||||
self.dialect = self.migration_context.dialect
|
||||
|
||||
self.imports = set()
|
||||
self.opts = opts
|
||||
self._has_batch = False
|
||||
|
||||
@util.memoized_property
|
||||
def inspector(self):
|
||||
return inspect(self.connection)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _within_batch(self):
|
||||
self._has_batch = True
|
||||
yield
|
||||
self._has_batch = False
|
||||
|
||||
def run_filters(self, object_, name, type_, reflected, compare_to):
|
||||
"""Run the context's object filters and return True if the targets
|
||||
should be part of the autogenerate operation.
|
||||
|
||||
This method should be run for every kind of object encountered within
|
||||
an autogenerate operation, giving the environment the chance
|
||||
to filter what objects should be included in the comparison.
|
||||
The filters here are produced directly via the
|
||||
:paramref:`.EnvironmentContext.configure.include_object`
|
||||
and :paramref:`.EnvironmentContext.configure.include_symbol`
|
||||
functions, if present.
|
||||
|
||||
"""
|
||||
for fn in self._object_filters:
|
||||
if not fn(object_, name, type_, reflected, compare_to):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@util.memoized_property
|
||||
def sorted_tables(self):
|
||||
"""Return an aggregate of the :attr:`.MetaData.sorted_tables` collection(s).
|
||||
|
||||
For a sequence of :class:`.MetaData` objects, this
|
||||
concatenates the :attr:`.MetaData.sorted_tables` collection
|
||||
for each individual :class:`.MetaData` in the order of the
|
||||
sequence. It does **not** collate the sorted tables collections.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
result = []
|
||||
for m in util.to_list(self.metadata):
|
||||
result.extend(m.sorted_tables)
|
||||
return result
|
||||
|
||||
@util.memoized_property
|
||||
def table_key_to_table(self):
|
||||
"""Return an aggregate of the :attr:`.MetaData.tables` dictionaries.
|
||||
|
||||
The :attr:`.MetaData.tables` collection is a dictionary of table key
|
||||
to :class:`.Table`; this method aggregates the dictionary across
|
||||
multiple :class:`.MetaData` objects into one dictionary.
|
||||
|
||||
Duplicate table keys are **not** supported; if two :class:`.MetaData`
|
||||
objects contain the same table key, an exception is raised.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
result = {}
|
||||
for m in util.to_list(self.metadata):
|
||||
intersect = set(result).intersection(set(m.tables))
|
||||
if intersect:
|
||||
raise ValueError(
|
||||
"Duplicate table keys across multiple "
|
||||
"MetaData objects: %s"
|
||||
% (", ".join('"%s"' % key for key in sorted(intersect)))
|
||||
)
|
||||
|
||||
result.update(m.tables)
|
||||
return result
|
||||
|
||||
|
||||
class RevisionContext(object):
|
||||
"""Maintains configuration and state that's specific to a revision
|
||||
file generation operation."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config,
|
||||
script_directory,
|
||||
command_args,
|
||||
process_revision_directives=None,
|
||||
):
|
||||
self.config = config
|
||||
self.script_directory = script_directory
|
||||
self.command_args = command_args
|
||||
self.process_revision_directives = process_revision_directives
|
||||
self.template_args = {
|
||||
"config": config # Let templates use config for
|
||||
# e.g. multiple databases
|
||||
}
|
||||
self.generated_revisions = [self._default_revision()]
|
||||
|
||||
def _to_script(self, migration_script):
|
||||
template_args = {}
|
||||
for k, v in self.template_args.items():
|
||||
template_args.setdefault(k, v)
|
||||
|
||||
if getattr(migration_script, "_needs_render", False):
|
||||
autogen_context = self._last_autogen_context
|
||||
|
||||
# clear out existing imports if we are doing multiple
|
||||
# renders
|
||||
autogen_context.imports = set()
|
||||
if migration_script.imports:
|
||||
autogen_context.imports.update(migration_script.imports)
|
||||
render._render_python_into_templatevars(
|
||||
autogen_context, migration_script, template_args
|
||||
)
|
||||
|
||||
return self.script_directory.generate_revision(
|
||||
migration_script.rev_id,
|
||||
migration_script.message,
|
||||
refresh=True,
|
||||
head=migration_script.head,
|
||||
splice=migration_script.splice,
|
||||
branch_labels=migration_script.branch_label,
|
||||
version_path=migration_script.version_path,
|
||||
depends_on=migration_script.depends_on,
|
||||
**template_args
|
||||
)
|
||||
|
||||
def run_autogenerate(self, rev, migration_context):
|
||||
self._run_environment(rev, migration_context, True)
|
||||
|
||||
def run_no_autogenerate(self, rev, migration_context):
|
||||
self._run_environment(rev, migration_context, False)
|
||||
|
||||
def _run_environment(self, rev, migration_context, autogenerate):
|
||||
if autogenerate:
|
||||
if self.command_args["sql"]:
|
||||
raise util.CommandError(
|
||||
"Using --sql with --autogenerate does not make any sense"
|
||||
)
|
||||
if set(self.script_directory.get_revisions(rev)) != set(
|
||||
self.script_directory.get_revisions("heads")
|
||||
):
|
||||
raise util.CommandError("Target database is not up to date.")
|
||||
|
||||
upgrade_token = migration_context.opts["upgrade_token"]
|
||||
downgrade_token = migration_context.opts["downgrade_token"]
|
||||
|
||||
migration_script = self.generated_revisions[-1]
|
||||
if not getattr(migration_script, "_needs_render", False):
|
||||
migration_script.upgrade_ops_list[-1].upgrade_token = upgrade_token
|
||||
migration_script.downgrade_ops_list[
|
||||
-1
|
||||
].downgrade_token = downgrade_token
|
||||
migration_script._needs_render = True
|
||||
else:
|
||||
migration_script._upgrade_ops.append(
|
||||
ops.UpgradeOps([], upgrade_token=upgrade_token)
|
||||
)
|
||||
migration_script._downgrade_ops.append(
|
||||
ops.DowngradeOps([], downgrade_token=downgrade_token)
|
||||
)
|
||||
|
||||
self._last_autogen_context = autogen_context = AutogenContext(
|
||||
migration_context, autogenerate=autogenerate
|
||||
)
|
||||
|
||||
if autogenerate:
|
||||
compare._populate_migration_script(
|
||||
autogen_context, migration_script
|
||||
)
|
||||
|
||||
if self.process_revision_directives:
|
||||
self.process_revision_directives(
|
||||
migration_context, rev, self.generated_revisions
|
||||
)
|
||||
|
||||
hook = migration_context.opts["process_revision_directives"]
|
||||
if hook:
|
||||
hook(migration_context, rev, self.generated_revisions)
|
||||
|
||||
for migration_script in self.generated_revisions:
|
||||
migration_script._needs_render = True
|
||||
|
||||
def _default_revision(self):
|
||||
op = ops.MigrationScript(
|
||||
rev_id=self.command_args["rev_id"] or util.rev_id(),
|
||||
message=self.command_args["message"],
|
||||
upgrade_ops=ops.UpgradeOps([]),
|
||||
downgrade_ops=ops.DowngradeOps([]),
|
||||
head=self.command_args["head"],
|
||||
splice=self.command_args["splice"],
|
||||
branch_label=self.command_args["branch_label"],
|
||||
version_path=self.command_args["version_path"],
|
||||
depends_on=self.command_args["depends_on"],
|
||||
)
|
||||
return op
|
||||
|
||||
def generate_scripts(self):
|
||||
for generated_revision in self.generated_revisions:
|
||||
yield self._to_script(generated_revision)
|
File diff suppressed because it is too large
Load Diff
@ -1,933 +0,0 @@
|
||||
import re
|
||||
|
||||
from mako.pygen import PythonPrinter
|
||||
from sqlalchemy import schema as sa_schema
|
||||
from sqlalchemy import sql
|
||||
from sqlalchemy import types as sqltypes
|
||||
|
||||
from .. import util
|
||||
from ..operations import ops
|
||||
from ..util import compat
|
||||
from ..util import sqla_compat
|
||||
from ..util.compat import string_types
|
||||
from ..util.compat import StringIO
|
||||
|
||||
|
||||
MAX_PYTHON_ARGS = 255
|
||||
|
||||
try:
|
||||
from sqlalchemy.sql.naming import conv
|
||||
|
||||
def _render_gen_name(autogen_context, name):
|
||||
if isinstance(name, conv):
|
||||
return _f_name(_alembic_autogenerate_prefix(autogen_context), name)
|
||||
else:
|
||||
return name
|
||||
|
||||
|
||||
except ImportError:
|
||||
|
||||
def _render_gen_name(autogen_context, name):
|
||||
return name
|
||||
|
||||
|
||||
def _indent(text):
|
||||
text = re.compile(r"^", re.M).sub(" ", text).strip()
|
||||
text = re.compile(r" +$", re.M).sub("", text)
|
||||
return text
|
||||
|
||||
|
||||
def _render_python_into_templatevars(
|
||||
autogen_context, migration_script, template_args
|
||||
):
|
||||
imports = autogen_context.imports
|
||||
|
||||
for upgrade_ops, downgrade_ops in zip(
|
||||
migration_script.upgrade_ops_list, migration_script.downgrade_ops_list
|
||||
):
|
||||
template_args[upgrade_ops.upgrade_token] = _indent(
|
||||
_render_cmd_body(upgrade_ops, autogen_context)
|
||||
)
|
||||
template_args[downgrade_ops.downgrade_token] = _indent(
|
||||
_render_cmd_body(downgrade_ops, autogen_context)
|
||||
)
|
||||
template_args["imports"] = "\n".join(sorted(imports))
|
||||
|
||||
|
||||
default_renderers = renderers = util.Dispatcher()
|
||||
|
||||
|
||||
def _render_cmd_body(op_container, autogen_context):
|
||||
|
||||
buf = StringIO()
|
||||
printer = PythonPrinter(buf)
|
||||
|
||||
printer.writeline(
|
||||
"# ### commands auto generated by Alembic - please adjust! ###"
|
||||
)
|
||||
|
||||
has_lines = False
|
||||
for op in op_container.ops:
|
||||
lines = render_op(autogen_context, op)
|
||||
has_lines = has_lines or lines
|
||||
|
||||
for line in lines:
|
||||
printer.writeline(line)
|
||||
|
||||
if not has_lines:
|
||||
printer.writeline("pass")
|
||||
|
||||
printer.writeline("# ### end Alembic commands ###")
|
||||
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def render_op(autogen_context, op):
|
||||
renderer = renderers.dispatch(op)
|
||||
lines = util.to_list(renderer(autogen_context, op))
|
||||
return lines
|
||||
|
||||
|
||||
def render_op_text(autogen_context, op):
|
||||
return "\n".join(render_op(autogen_context, op))
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.ModifyTableOps)
|
||||
def _render_modify_table(autogen_context, op):
|
||||
opts = autogen_context.opts
|
||||
render_as_batch = opts.get("render_as_batch", False)
|
||||
|
||||
if op.ops:
|
||||
lines = []
|
||||
if render_as_batch:
|
||||
with autogen_context._within_batch():
|
||||
lines.append(
|
||||
"with op.batch_alter_table(%r, schema=%r) as batch_op:"
|
||||
% (op.table_name, op.schema)
|
||||
)
|
||||
for t_op in op.ops:
|
||||
t_lines = render_op(autogen_context, t_op)
|
||||
lines.extend(t_lines)
|
||||
lines.append("")
|
||||
else:
|
||||
for t_op in op.ops:
|
||||
t_lines = render_op(autogen_context, t_op)
|
||||
lines.extend(t_lines)
|
||||
|
||||
return lines
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateTableCommentOp)
|
||||
def _render_create_table_comment(autogen_context, op):
|
||||
|
||||
templ = (
|
||||
"{prefix}create_table_comment(\n"
|
||||
"{indent}'{tname}',\n"
|
||||
"{indent}{comment},\n"
|
||||
"{indent}existing_comment={existing},\n"
|
||||
"{indent}schema={schema}\n"
|
||||
")"
|
||||
)
|
||||
return templ.format(
|
||||
prefix=_alembic_autogenerate_prefix(autogen_context),
|
||||
tname=op.table_name,
|
||||
comment="%r" % op.comment if op.comment is not None else None,
|
||||
existing="%r" % op.existing_comment
|
||||
if op.existing_comment is not None
|
||||
else None,
|
||||
schema="'%s'" % op.schema if op.schema is not None else None,
|
||||
indent=" ",
|
||||
)
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.DropTableCommentOp)
|
||||
def _render_drop_table_comment(autogen_context, op):
|
||||
|
||||
templ = (
|
||||
"{prefix}drop_table_comment(\n"
|
||||
"{indent}'{tname}',\n"
|
||||
"{indent}existing_comment={existing},\n"
|
||||
"{indent}schema={schema}\n"
|
||||
")"
|
||||
)
|
||||
return templ.format(
|
||||
prefix=_alembic_autogenerate_prefix(autogen_context),
|
||||
tname=op.table_name,
|
||||
existing="%r" % op.existing_comment
|
||||
if op.existing_comment is not None
|
||||
else None,
|
||||
schema="'%s'" % op.schema if op.schema is not None else None,
|
||||
indent=" ",
|
||||
)
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateTableOp)
|
||||
def _add_table(autogen_context, op):
|
||||
table = op.to_table()
|
||||
|
||||
args = [
|
||||
col
|
||||
for col in [
|
||||
_render_column(col, autogen_context) for col in table.columns
|
||||
]
|
||||
if col
|
||||
] + sorted(
|
||||
[
|
||||
rcons
|
||||
for rcons in [
|
||||
_render_constraint(cons, autogen_context)
|
||||
for cons in table.constraints
|
||||
]
|
||||
if rcons is not None
|
||||
]
|
||||
)
|
||||
|
||||
if len(args) > MAX_PYTHON_ARGS:
|
||||
args = "*[" + ",\n".join(args) + "]"
|
||||
else:
|
||||
args = ",\n".join(args)
|
||||
|
||||
text = "%(prefix)screate_table(%(tablename)r,\n%(args)s" % {
|
||||
"tablename": _ident(op.table_name),
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"args": args,
|
||||
}
|
||||
if op.schema:
|
||||
text += ",\nschema=%r" % _ident(op.schema)
|
||||
|
||||
comment = sqla_compat._comment_attribute(table)
|
||||
if comment:
|
||||
text += ",\ncomment=%r" % _ident(comment)
|
||||
for k in sorted(op.kw):
|
||||
text += ",\n%s=%r" % (k.replace(" ", "_"), op.kw[k])
|
||||
text += "\n)"
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.DropTableOp)
|
||||
def _drop_table(autogen_context, op):
|
||||
text = "%(prefix)sdrop_table(%(tname)r" % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"tname": _ident(op.table_name),
|
||||
}
|
||||
if op.schema:
|
||||
text += ", schema=%r" % _ident(op.schema)
|
||||
text += ")"
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateIndexOp)
|
||||
def _add_index(autogen_context, op):
|
||||
index = op.to_index()
|
||||
|
||||
has_batch = autogen_context._has_batch
|
||||
|
||||
if has_batch:
|
||||
tmpl = (
|
||||
"%(prefix)screate_index(%(name)r, [%(columns)s], "
|
||||
"unique=%(unique)r%(kwargs)s)"
|
||||
)
|
||||
else:
|
||||
tmpl = (
|
||||
"%(prefix)screate_index(%(name)r, %(table)r, [%(columns)s], "
|
||||
"unique=%(unique)r%(schema)s%(kwargs)s)"
|
||||
)
|
||||
|
||||
text = tmpl % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"name": _render_gen_name(autogen_context, index.name),
|
||||
"table": _ident(index.table.name),
|
||||
"columns": ", ".join(
|
||||
_get_index_rendered_expressions(index, autogen_context)
|
||||
),
|
||||
"unique": index.unique or False,
|
||||
"schema": (", schema=%r" % _ident(index.table.schema))
|
||||
if index.table.schema
|
||||
else "",
|
||||
"kwargs": (
|
||||
", "
|
||||
+ ", ".join(
|
||||
[
|
||||
"%s=%s"
|
||||
% (key, _render_potential_expr(val, autogen_context))
|
||||
for key, val in index.kwargs.items()
|
||||
]
|
||||
)
|
||||
)
|
||||
if len(index.kwargs)
|
||||
else "",
|
||||
}
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.DropIndexOp)
|
||||
def _drop_index(autogen_context, op):
|
||||
has_batch = autogen_context._has_batch
|
||||
|
||||
if has_batch:
|
||||
tmpl = "%(prefix)sdrop_index(%(name)r)"
|
||||
else:
|
||||
tmpl = (
|
||||
"%(prefix)sdrop_index(%(name)r, "
|
||||
"table_name=%(table_name)r%(schema)s)"
|
||||
)
|
||||
|
||||
text = tmpl % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"name": _render_gen_name(autogen_context, op.index_name),
|
||||
"table_name": _ident(op.table_name),
|
||||
"schema": ((", schema=%r" % _ident(op.schema)) if op.schema else ""),
|
||||
}
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateUniqueConstraintOp)
|
||||
def _add_unique_constraint(autogen_context, op):
|
||||
return [_uq_constraint(op.to_constraint(), autogen_context, True)]
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateForeignKeyOp)
|
||||
def _add_fk_constraint(autogen_context, op):
|
||||
|
||||
args = [repr(_render_gen_name(autogen_context, op.constraint_name))]
|
||||
if not autogen_context._has_batch:
|
||||
args.append(repr(_ident(op.source_table)))
|
||||
|
||||
args.extend(
|
||||
[
|
||||
repr(_ident(op.referent_table)),
|
||||
repr([_ident(col) for col in op.local_cols]),
|
||||
repr([_ident(col) for col in op.remote_cols]),
|
||||
]
|
||||
)
|
||||
|
||||
kwargs = [
|
||||
"referent_schema",
|
||||
"onupdate",
|
||||
"ondelete",
|
||||
"initially",
|
||||
"deferrable",
|
||||
"use_alter",
|
||||
]
|
||||
if not autogen_context._has_batch:
|
||||
kwargs.insert(0, "source_schema")
|
||||
|
||||
for k in kwargs:
|
||||
if k in op.kw:
|
||||
value = op.kw[k]
|
||||
if value is not None:
|
||||
args.append("%s=%r" % (k, value))
|
||||
|
||||
return "%(prefix)screate_foreign_key(%(args)s)" % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"args": ", ".join(args),
|
||||
}
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreatePrimaryKeyOp)
|
||||
def _add_pk_constraint(constraint, autogen_context):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.CreateCheckConstraintOp)
|
||||
def _add_check_constraint(constraint, autogen_context):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.DropConstraintOp)
|
||||
def _drop_constraint(autogen_context, op):
|
||||
|
||||
if autogen_context._has_batch:
|
||||
template = "%(prefix)sdrop_constraint" "(%(name)r, type_=%(type)r)"
|
||||
else:
|
||||
template = (
|
||||
"%(prefix)sdrop_constraint"
|
||||
"(%(name)r, '%(table_name)s'%(schema)s, type_=%(type)r)"
|
||||
)
|
||||
|
||||
text = template % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"name": _render_gen_name(autogen_context, op.constraint_name),
|
||||
"table_name": _ident(op.table_name),
|
||||
"type": op.constraint_type,
|
||||
"schema": (", schema=%r" % _ident(op.schema)) if op.schema else "",
|
||||
}
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.AddColumnOp)
|
||||
def _add_column(autogen_context, op):
|
||||
|
||||
schema, tname, column = op.schema, op.table_name, op.column
|
||||
if autogen_context._has_batch:
|
||||
template = "%(prefix)sadd_column(%(column)s)"
|
||||
else:
|
||||
template = "%(prefix)sadd_column(%(tname)r, %(column)s"
|
||||
if schema:
|
||||
template += ", schema=%(schema)r"
|
||||
template += ")"
|
||||
text = template % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"tname": tname,
|
||||
"column": _render_column(column, autogen_context),
|
||||
"schema": schema,
|
||||
}
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.DropColumnOp)
|
||||
def _drop_column(autogen_context, op):
|
||||
|
||||
schema, tname, column_name = op.schema, op.table_name, op.column_name
|
||||
|
||||
if autogen_context._has_batch:
|
||||
template = "%(prefix)sdrop_column(%(cname)r)"
|
||||
else:
|
||||
template = "%(prefix)sdrop_column(%(tname)r, %(cname)r"
|
||||
if schema:
|
||||
template += ", schema=%(schema)r"
|
||||
template += ")"
|
||||
|
||||
text = template % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"tname": _ident(tname),
|
||||
"cname": _ident(column_name),
|
||||
"schema": _ident(schema),
|
||||
}
|
||||
return text
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.AlterColumnOp)
|
||||
def _alter_column(autogen_context, op):
|
||||
|
||||
tname = op.table_name
|
||||
cname = op.column_name
|
||||
server_default = op.modify_server_default
|
||||
type_ = op.modify_type
|
||||
nullable = op.modify_nullable
|
||||
comment = op.modify_comment
|
||||
autoincrement = op.kw.get("autoincrement", None)
|
||||
existing_type = op.existing_type
|
||||
existing_nullable = op.existing_nullable
|
||||
existing_comment = op.existing_comment
|
||||
existing_server_default = op.existing_server_default
|
||||
schema = op.schema
|
||||
|
||||
indent = " " * 11
|
||||
|
||||
if autogen_context._has_batch:
|
||||
template = "%(prefix)salter_column(%(cname)r"
|
||||
else:
|
||||
template = "%(prefix)salter_column(%(tname)r, %(cname)r"
|
||||
|
||||
text = template % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"tname": tname,
|
||||
"cname": cname,
|
||||
}
|
||||
if existing_type is not None:
|
||||
text += ",\n%sexisting_type=%s" % (
|
||||
indent,
|
||||
_repr_type(existing_type, autogen_context),
|
||||
)
|
||||
if server_default is not False:
|
||||
rendered = _render_server_default(server_default, autogen_context)
|
||||
text += ",\n%sserver_default=%s" % (indent, rendered)
|
||||
|
||||
if type_ is not None:
|
||||
text += ",\n%stype_=%s" % (indent, _repr_type(type_, autogen_context))
|
||||
if nullable is not None:
|
||||
text += ",\n%snullable=%r" % (indent, nullable)
|
||||
if comment is not False:
|
||||
text += ",\n%scomment=%r" % (indent, comment)
|
||||
if existing_comment is not None:
|
||||
text += ",\n%sexisting_comment=%r" % (indent, existing_comment)
|
||||
if nullable is None and existing_nullable is not None:
|
||||
text += ",\n%sexisting_nullable=%r" % (indent, existing_nullable)
|
||||
if autoincrement is not None:
|
||||
text += ",\n%sautoincrement=%r" % (indent, autoincrement)
|
||||
if server_default is False and existing_server_default:
|
||||
rendered = _render_server_default(
|
||||
existing_server_default, autogen_context
|
||||
)
|
||||
text += ",\n%sexisting_server_default=%s" % (indent, rendered)
|
||||
if schema and not autogen_context._has_batch:
|
||||
text += ",\n%sschema=%r" % (indent, schema)
|
||||
text += ")"
|
||||
return text
|
||||
|
||||
|
||||
class _f_name(object):
|
||||
def __init__(self, prefix, name):
|
||||
self.prefix = prefix
|
||||
self.name = name
|
||||
|
||||
def __repr__(self):
|
||||
return "%sf(%r)" % (self.prefix, _ident(self.name))
|
||||
|
||||
|
||||
def _ident(name):
|
||||
"""produce a __repr__() object for a string identifier that may
|
||||
use quoted_name() in SQLAlchemy 0.9 and greater.
|
||||
|
||||
The issue worked around here is that quoted_name() doesn't have
|
||||
very good repr() behavior by itself when unicode is involved.
|
||||
|
||||
"""
|
||||
if name is None:
|
||||
return name
|
||||
elif isinstance(name, sql.elements.quoted_name):
|
||||
if compat.py2k:
|
||||
# the attempt to encode to ascii here isn't super ideal,
|
||||
# however we are trying to cut down on an explosion of
|
||||
# u'' literals only when py2k + SQLA 0.9, in particular
|
||||
# makes unit tests testing code generation very difficult
|
||||
try:
|
||||
return name.encode("ascii")
|
||||
except UnicodeError:
|
||||
return compat.text_type(name)
|
||||
else:
|
||||
return compat.text_type(name)
|
||||
elif isinstance(name, compat.string_types):
|
||||
return name
|
||||
|
||||
|
||||
def _render_potential_expr(
|
||||
value, autogen_context, wrap_in_text=True, is_server_default=False
|
||||
):
|
||||
if isinstance(value, sql.ClauseElement):
|
||||
|
||||
if wrap_in_text:
|
||||
template = "%(prefix)stext(%(sql)r)"
|
||||
else:
|
||||
template = "%(sql)r"
|
||||
|
||||
return template % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"sql": autogen_context.migration_context.impl.render_ddl_sql_expr(
|
||||
value, is_server_default=is_server_default
|
||||
),
|
||||
}
|
||||
|
||||
else:
|
||||
return repr(value)
|
||||
|
||||
|
||||
def _get_index_rendered_expressions(idx, autogen_context):
|
||||
return [
|
||||
repr(_ident(getattr(exp, "name", None)))
|
||||
if isinstance(exp, sa_schema.Column)
|
||||
else _render_potential_expr(exp, autogen_context)
|
||||
for exp in idx.expressions
|
||||
]
|
||||
|
||||
|
||||
def _uq_constraint(constraint, autogen_context, alter):
|
||||
opts = []
|
||||
|
||||
has_batch = autogen_context._has_batch
|
||||
|
||||
if constraint.deferrable:
|
||||
opts.append(("deferrable", str(constraint.deferrable)))
|
||||
if constraint.initially:
|
||||
opts.append(("initially", str(constraint.initially)))
|
||||
if not has_batch and alter and constraint.table.schema:
|
||||
opts.append(("schema", _ident(constraint.table.schema)))
|
||||
if not alter and constraint.name:
|
||||
opts.append(
|
||||
("name", _render_gen_name(autogen_context, constraint.name))
|
||||
)
|
||||
|
||||
if alter:
|
||||
args = [repr(_render_gen_name(autogen_context, constraint.name))]
|
||||
if not has_batch:
|
||||
args += [repr(_ident(constraint.table.name))]
|
||||
args.append(repr([_ident(col.name) for col in constraint.columns]))
|
||||
args.extend(["%s=%r" % (k, v) for k, v in opts])
|
||||
return "%(prefix)screate_unique_constraint(%(args)s)" % {
|
||||
"prefix": _alembic_autogenerate_prefix(autogen_context),
|
||||
"args": ", ".join(args),
|
||||
}
|
||||
else:
|
||||
args = [repr(_ident(col.name)) for col in constraint.columns]
|
||||
args.extend(["%s=%r" % (k, v) for k, v in opts])
|
||||
return "%(prefix)sUniqueConstraint(%(args)s)" % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"args": ", ".join(args),
|
||||
}
|
||||
|
||||
|
||||
def _user_autogenerate_prefix(autogen_context, target):
|
||||
prefix = autogen_context.opts["user_module_prefix"]
|
||||
if prefix is None:
|
||||
return "%s." % target.__module__
|
||||
else:
|
||||
return prefix
|
||||
|
||||
|
||||
def _sqlalchemy_autogenerate_prefix(autogen_context):
|
||||
return autogen_context.opts["sqlalchemy_module_prefix"] or ""
|
||||
|
||||
|
||||
def _alembic_autogenerate_prefix(autogen_context):
|
||||
if autogen_context._has_batch:
|
||||
return "batch_op."
|
||||
else:
|
||||
return autogen_context.opts["alembic_module_prefix"] or ""
|
||||
|
||||
|
||||
def _user_defined_render(type_, object_, autogen_context):
|
||||
if "render_item" in autogen_context.opts:
|
||||
render = autogen_context.opts["render_item"]
|
||||
if render:
|
||||
rendered = render(type_, object_, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
return False
|
||||
|
||||
|
||||
def _render_column(column, autogen_context):
|
||||
rendered = _user_defined_render("column", column, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
args = []
|
||||
opts = []
|
||||
|
||||
if column.server_default:
|
||||
if sqla_compat._server_default_is_computed(column):
|
||||
rendered = _render_computed(column.computed, autogen_context)
|
||||
if rendered:
|
||||
args.append(rendered)
|
||||
else:
|
||||
rendered = _render_server_default(
|
||||
column.server_default, autogen_context
|
||||
)
|
||||
if rendered:
|
||||
opts.append(("server_default", rendered))
|
||||
|
||||
if (
|
||||
column.autoincrement is not None
|
||||
and column.autoincrement != sqla_compat.AUTOINCREMENT_DEFAULT
|
||||
):
|
||||
opts.append(("autoincrement", column.autoincrement))
|
||||
|
||||
if column.nullable is not None:
|
||||
opts.append(("nullable", column.nullable))
|
||||
|
||||
if column.system:
|
||||
opts.append(("system", column.system))
|
||||
|
||||
comment = sqla_compat._comment_attribute(column)
|
||||
if comment:
|
||||
opts.append(("comment", "%r" % comment))
|
||||
|
||||
# TODO: for non-ascii colname, assign a "key"
|
||||
return "%(prefix)sColumn(%(name)r, %(type)s, %(args)s%(kwargs)s)" % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"name": _ident(column.name),
|
||||
"type": _repr_type(column.type, autogen_context),
|
||||
"args": ", ".join([str(arg) for arg in args]) + ", " if args else "",
|
||||
"kwargs": (
|
||||
", ".join(
|
||||
["%s=%s" % (kwname, val) for kwname, val in opts]
|
||||
+ [
|
||||
"%s=%s"
|
||||
% (key, _render_potential_expr(val, autogen_context))
|
||||
for key, val in sqla_compat._column_kwargs(column).items()
|
||||
]
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _render_server_default(default, autogen_context, repr_=True):
|
||||
rendered = _user_defined_render("server_default", default, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
if sqla_compat.has_computed and isinstance(default, sa_schema.Computed):
|
||||
return _render_computed(default, autogen_context)
|
||||
elif isinstance(default, sa_schema.DefaultClause):
|
||||
if isinstance(default.arg, compat.string_types):
|
||||
default = default.arg
|
||||
else:
|
||||
return _render_potential_expr(
|
||||
default.arg, autogen_context, is_server_default=True
|
||||
)
|
||||
|
||||
if isinstance(default, string_types) and repr_:
|
||||
default = repr(re.sub(r"^'|'$", "", default))
|
||||
|
||||
return default
|
||||
|
||||
|
||||
def _render_computed(computed, autogen_context):
|
||||
text = _render_potential_expr(
|
||||
computed.sqltext, autogen_context, wrap_in_text=False
|
||||
)
|
||||
|
||||
kwargs = {}
|
||||
if computed.persisted is not None:
|
||||
kwargs["persisted"] = computed.persisted
|
||||
return "%(prefix)sComputed(%(text)s, %(kwargs)s)" % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"text": text,
|
||||
"kwargs": (", ".join("%s=%s" % pair for pair in kwargs.items())),
|
||||
}
|
||||
|
||||
|
||||
def _repr_type(type_, autogen_context):
|
||||
rendered = _user_defined_render("type", type_, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
if hasattr(autogen_context.migration_context, "impl"):
|
||||
impl_rt = autogen_context.migration_context.impl.render_type(
|
||||
type_, autogen_context
|
||||
)
|
||||
else:
|
||||
impl_rt = None
|
||||
|
||||
mod = type(type_).__module__
|
||||
imports = autogen_context.imports
|
||||
if mod.startswith("sqlalchemy.dialects"):
|
||||
dname = re.match(r"sqlalchemy\.dialects\.(\w+)", mod).group(1)
|
||||
if imports is not None:
|
||||
imports.add("from sqlalchemy.dialects import %s" % dname)
|
||||
if impl_rt:
|
||||
return impl_rt
|
||||
else:
|
||||
return "%s.%r" % (dname, type_)
|
||||
elif impl_rt:
|
||||
return impl_rt
|
||||
elif mod.startswith("sqlalchemy."):
|
||||
if type(type_) is sqltypes.Variant:
|
||||
return _render_Variant_type(type_, autogen_context)
|
||||
if "_render_%s_type" % type_.__visit_name__ in globals():
|
||||
fn = globals()["_render_%s_type" % type_.__visit_name__]
|
||||
return fn(type_, autogen_context)
|
||||
else:
|
||||
prefix = _sqlalchemy_autogenerate_prefix(autogen_context)
|
||||
return "%s%r" % (prefix, type_)
|
||||
else:
|
||||
prefix = _user_autogenerate_prefix(autogen_context, type_)
|
||||
return "%s%r" % (prefix, type_)
|
||||
|
||||
|
||||
def _render_ARRAY_type(type_, autogen_context):
|
||||
return _render_type_w_subtype(
|
||||
type_, autogen_context, "item_type", r"(.+?\()"
|
||||
)
|
||||
|
||||
|
||||
def _render_Variant_type(type_, autogen_context):
|
||||
base = _repr_type(type_.impl, autogen_context)
|
||||
for dialect in sorted(type_.mapping):
|
||||
typ = type_.mapping[dialect]
|
||||
base += ".with_variant(%s, %r)" % (
|
||||
_repr_type(typ, autogen_context),
|
||||
dialect,
|
||||
)
|
||||
return base
|
||||
|
||||
|
||||
def _render_type_w_subtype(
|
||||
type_, autogen_context, attrname, regexp, prefix=None
|
||||
):
|
||||
outer_repr = repr(type_)
|
||||
inner_type = getattr(type_, attrname, None)
|
||||
if inner_type is None:
|
||||
return False
|
||||
|
||||
inner_repr = repr(inner_type)
|
||||
|
||||
inner_repr = re.sub(r"([\(\)])", r"\\\1", inner_repr)
|
||||
sub_type = _repr_type(getattr(type_, attrname), autogen_context)
|
||||
outer_type = re.sub(regexp + inner_repr, r"\1%s" % sub_type, outer_repr)
|
||||
|
||||
if prefix:
|
||||
return "%s%s" % (prefix, outer_type)
|
||||
|
||||
mod = type(type_).__module__
|
||||
if mod.startswith("sqlalchemy.dialects"):
|
||||
dname = re.match(r"sqlalchemy\.dialects\.(\w+)", mod).group(1)
|
||||
return "%s.%s" % (dname, outer_type)
|
||||
elif mod.startswith("sqlalchemy"):
|
||||
prefix = _sqlalchemy_autogenerate_prefix(autogen_context)
|
||||
return "%s%s" % (prefix, outer_type)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
_constraint_renderers = util.Dispatcher()
|
||||
|
||||
|
||||
def _render_constraint(constraint, autogen_context):
|
||||
try:
|
||||
renderer = _constraint_renderers.dispatch(constraint)
|
||||
except ValueError:
|
||||
util.warn("No renderer is established for object %r" % constraint)
|
||||
return "[Unknown Python object %r]" % constraint
|
||||
else:
|
||||
return renderer(constraint, autogen_context)
|
||||
|
||||
|
||||
@_constraint_renderers.dispatch_for(sa_schema.PrimaryKeyConstraint)
|
||||
def _render_primary_key(constraint, autogen_context):
|
||||
rendered = _user_defined_render("primary_key", constraint, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
if not constraint.columns:
|
||||
return None
|
||||
|
||||
opts = []
|
||||
if constraint.name:
|
||||
opts.append(
|
||||
("name", repr(_render_gen_name(autogen_context, constraint.name)))
|
||||
)
|
||||
return "%(prefix)sPrimaryKeyConstraint(%(args)s)" % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"args": ", ".join(
|
||||
[repr(c.name) for c in constraint.columns]
|
||||
+ ["%s=%s" % (kwname, val) for kwname, val in opts]
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _fk_colspec(fk, metadata_schema):
|
||||
"""Implement a 'safe' version of ForeignKey._get_colspec() that
|
||||
won't fail if the remote table can't be resolved.
|
||||
|
||||
"""
|
||||
colspec = fk._get_colspec()
|
||||
tokens = colspec.split(".")
|
||||
tname, colname = tokens[-2:]
|
||||
|
||||
if metadata_schema is not None and len(tokens) == 2:
|
||||
table_fullname = "%s.%s" % (metadata_schema, tname)
|
||||
else:
|
||||
table_fullname = ".".join(tokens[0:-1])
|
||||
|
||||
if (
|
||||
not fk.link_to_name
|
||||
and fk.parent is not None
|
||||
and fk.parent.table is not None
|
||||
):
|
||||
# try to resolve the remote table in order to adjust for column.key.
|
||||
# the FK constraint needs to be rendered in terms of the column
|
||||
# name.
|
||||
parent_metadata = fk.parent.table.metadata
|
||||
if table_fullname in parent_metadata.tables:
|
||||
col = parent_metadata.tables[table_fullname].c.get(colname)
|
||||
if col is not None:
|
||||
colname = _ident(col.name)
|
||||
|
||||
colspec = "%s.%s" % (table_fullname, colname)
|
||||
|
||||
return colspec
|
||||
|
||||
|
||||
def _populate_render_fk_opts(constraint, opts):
|
||||
|
||||
if constraint.onupdate:
|
||||
opts.append(("onupdate", repr(constraint.onupdate)))
|
||||
if constraint.ondelete:
|
||||
opts.append(("ondelete", repr(constraint.ondelete)))
|
||||
if constraint.initially:
|
||||
opts.append(("initially", repr(constraint.initially)))
|
||||
if constraint.deferrable:
|
||||
opts.append(("deferrable", repr(constraint.deferrable)))
|
||||
if constraint.use_alter:
|
||||
opts.append(("use_alter", repr(constraint.use_alter)))
|
||||
|
||||
|
||||
@_constraint_renderers.dispatch_for(sa_schema.ForeignKeyConstraint)
|
||||
def _render_foreign_key(constraint, autogen_context):
|
||||
rendered = _user_defined_render("foreign_key", constraint, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
opts = []
|
||||
if constraint.name:
|
||||
opts.append(
|
||||
("name", repr(_render_gen_name(autogen_context, constraint.name)))
|
||||
)
|
||||
|
||||
_populate_render_fk_opts(constraint, opts)
|
||||
|
||||
apply_metadata_schema = constraint.parent.metadata.schema
|
||||
return (
|
||||
"%(prefix)sForeignKeyConstraint([%(cols)s], "
|
||||
"[%(refcols)s], %(args)s)"
|
||||
% {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"cols": ", ".join(
|
||||
"%r" % _ident(f.parent.name) for f in constraint.elements
|
||||
),
|
||||
"refcols": ", ".join(
|
||||
repr(_fk_colspec(f, apply_metadata_schema))
|
||||
for f in constraint.elements
|
||||
),
|
||||
"args": ", ".join(
|
||||
["%s=%s" % (kwname, val) for kwname, val in opts]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@_constraint_renderers.dispatch_for(sa_schema.UniqueConstraint)
|
||||
def _render_unique_constraint(constraint, autogen_context):
|
||||
rendered = _user_defined_render("unique", constraint, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
return _uq_constraint(constraint, autogen_context, False)
|
||||
|
||||
|
||||
@_constraint_renderers.dispatch_for(sa_schema.CheckConstraint)
|
||||
def _render_check_constraint(constraint, autogen_context):
|
||||
rendered = _user_defined_render("check", constraint, autogen_context)
|
||||
if rendered is not False:
|
||||
return rendered
|
||||
|
||||
# detect the constraint being part of
|
||||
# a parent type which is probably in the Table already.
|
||||
# ideally SQLAlchemy would give us more of a first class
|
||||
# way to detect this.
|
||||
if (
|
||||
constraint._create_rule
|
||||
and hasattr(constraint._create_rule, "target")
|
||||
and isinstance(constraint._create_rule.target, sqltypes.TypeEngine)
|
||||
):
|
||||
return None
|
||||
opts = []
|
||||
if constraint.name:
|
||||
opts.append(
|
||||
("name", repr(_render_gen_name(autogen_context, constraint.name)))
|
||||
)
|
||||
return "%(prefix)sCheckConstraint(%(sqltext)s%(opts)s)" % {
|
||||
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
|
||||
"opts": ", " + (", ".join("%s=%s" % (k, v) for k, v in opts))
|
||||
if opts
|
||||
else "",
|
||||
"sqltext": _render_potential_expr(
|
||||
constraint.sqltext, autogen_context, wrap_in_text=False
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@renderers.dispatch_for(ops.ExecuteSQLOp)
|
||||
def _execute_sql(autogen_context, op):
|
||||
if not isinstance(op.sqltext, string_types):
|
||||
raise NotImplementedError(
|
||||
"Autogenerate rendering of SQL Expression language constructs "
|
||||
"not supported here; please use a plain SQL string"
|
||||
)
|
||||
return "op.execute(%r)" % op.sqltext
|
||||
|
||||
|
||||
renderers = default_renderers.branch()
|
@ -1,158 +0,0 @@
|
||||
from alembic import util
|
||||
from alembic.operations import ops
|
||||
|
||||
|
||||
class Rewriter(object):
|
||||
"""A helper object that allows easy 'rewriting' of ops streams.
|
||||
|
||||
The :class:`.Rewriter` object is intended to be passed along
|
||||
to the
|
||||
:paramref:`.EnvironmentContext.configure.process_revision_directives`
|
||||
parameter in an ``env.py`` script. Once constructed, any number
|
||||
of "rewrites" functions can be associated with it, which will be given
|
||||
the opportunity to modify the structure without having to have explicit
|
||||
knowledge of the overall structure.
|
||||
|
||||
The function is passed the :class:`.MigrationContext` object and
|
||||
``revision`` tuple that are passed to the :paramref:`.Environment
|
||||
Context.configure.process_revision_directives` function normally,
|
||||
and the third argument is an individual directive of the type
|
||||
noted in the decorator. The function has the choice of returning
|
||||
a single op directive, which normally can be the directive that
|
||||
was actually passed, or a new directive to replace it, or a list
|
||||
of zero or more directives to replace it.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`autogen_rewriter` - usage example
|
||||
|
||||
.. versionadded:: 0.8
|
||||
|
||||
"""
|
||||
|
||||
_traverse = util.Dispatcher()
|
||||
|
||||
_chained = None
|
||||
|
||||
def __init__(self):
|
||||
self.dispatch = util.Dispatcher()
|
||||
|
||||
def chain(self, other):
|
||||
"""Produce a "chain" of this :class:`.Rewriter` to another.
|
||||
|
||||
This allows two rewriters to operate serially on a stream,
|
||||
e.g.::
|
||||
|
||||
writer1 = autogenerate.Rewriter()
|
||||
writer2 = autogenerate.Rewriter()
|
||||
|
||||
@writer1.rewrites(ops.AddColumnOp)
|
||||
def add_column_nullable(context, revision, op):
|
||||
op.column.nullable = True
|
||||
return op
|
||||
|
||||
@writer2.rewrites(ops.AddColumnOp)
|
||||
def add_column_idx(context, revision, op):
|
||||
idx_op = ops.CreateIndexOp(
|
||||
'ixc', op.table_name, [op.column.name])
|
||||
return [
|
||||
op,
|
||||
idx_op
|
||||
]
|
||||
|
||||
writer = writer1.chain(writer2)
|
||||
|
||||
:param other: a :class:`.Rewriter` instance
|
||||
:return: a new :class:`.Rewriter` that will run the operations
|
||||
of this writer, then the "other" writer, in succession.
|
||||
|
||||
"""
|
||||
wr = self.__class__.__new__(self.__class__)
|
||||
wr.__dict__.update(self.__dict__)
|
||||
wr._chained = other
|
||||
return wr
|
||||
|
||||
def rewrites(self, operator):
|
||||
"""Register a function as rewriter for a given type.
|
||||
|
||||
The function should receive three arguments, which are
|
||||
the :class:`.MigrationContext`, a ``revision`` tuple, and
|
||||
an op directive of the type indicated. E.g.::
|
||||
|
||||
@writer1.rewrites(ops.AddColumnOp)
|
||||
def add_column_nullable(context, revision, op):
|
||||
op.column.nullable = True
|
||||
return op
|
||||
|
||||
"""
|
||||
return self.dispatch.dispatch_for(operator)
|
||||
|
||||
def _rewrite(self, context, revision, directive):
|
||||
try:
|
||||
_rewriter = self.dispatch.dispatch(directive)
|
||||
except ValueError:
|
||||
_rewriter = None
|
||||
yield directive
|
||||
else:
|
||||
if self in directive._mutations:
|
||||
yield directive
|
||||
else:
|
||||
for r_directive in util.to_list(
|
||||
_rewriter(context, revision, directive)
|
||||
):
|
||||
r_directive._mutations = r_directive._mutations.union(
|
||||
[self]
|
||||
)
|
||||
yield r_directive
|
||||
|
||||
def __call__(self, context, revision, directives):
|
||||
self.process_revision_directives(context, revision, directives)
|
||||
if self._chained:
|
||||
self._chained(context, revision, directives)
|
||||
|
||||
@_traverse.dispatch_for(ops.MigrationScript)
|
||||
def _traverse_script(self, context, revision, directive):
|
||||
upgrade_ops_list = []
|
||||
for upgrade_ops in directive.upgrade_ops_list:
|
||||
ret = self._traverse_for(context, revision, upgrade_ops)
|
||||
if len(ret) != 1:
|
||||
raise ValueError(
|
||||
"Can only return single object for UpgradeOps traverse"
|
||||
)
|
||||
upgrade_ops_list.append(ret[0])
|
||||
directive.upgrade_ops = upgrade_ops_list
|
||||
|
||||
downgrade_ops_list = []
|
||||
for downgrade_ops in directive.downgrade_ops_list:
|
||||
ret = self._traverse_for(context, revision, downgrade_ops)
|
||||
if len(ret) != 1:
|
||||
raise ValueError(
|
||||
"Can only return single object for DowngradeOps traverse"
|
||||
)
|
||||
downgrade_ops_list.append(ret[0])
|
||||
directive.downgrade_ops = downgrade_ops_list
|
||||
|
||||
@_traverse.dispatch_for(ops.OpContainer)
|
||||
def _traverse_op_container(self, context, revision, directive):
|
||||
self._traverse_list(context, revision, directive.ops)
|
||||
|
||||
@_traverse.dispatch_for(ops.MigrateOperation)
|
||||
def _traverse_any_directive(self, context, revision, directive):
|
||||
pass
|
||||
|
||||
def _traverse_for(self, context, revision, directive):
|
||||
directives = list(self._rewrite(context, revision, directive))
|
||||
for directive in directives:
|
||||
traverser = self._traverse.dispatch(directive)
|
||||
traverser(self, context, revision, directive)
|
||||
return directives
|
||||
|
||||
def _traverse_list(self, context, revision, directives):
|
||||
dest = []
|
||||
for directive in directives:
|
||||
dest.extend(self._traverse_for(context, revision, directive))
|
||||
|
||||
directives[:] = dest
|
||||
|
||||
def process_revision_directives(self, context, revision, directives):
|
||||
self._traverse_list(context, revision, directives)
|
@ -1,611 +0,0 @@
|
||||
import os
|
||||
|
||||
from . import autogenerate as autogen
|
||||
from . import util
|
||||
from .runtime.environment import EnvironmentContext
|
||||
from .script import ScriptDirectory
|
||||
|
||||
|
||||
def list_templates(config):
|
||||
"""List available templates.
|
||||
|
||||
:param config: a :class:`.Config` object.
|
||||
|
||||
"""
|
||||
|
||||
config.print_stdout("Available templates:\n")
|
||||
for tempname in os.listdir(config.get_template_directory()):
|
||||
with open(
|
||||
os.path.join(config.get_template_directory(), tempname, "README")
|
||||
) as readme:
|
||||
synopsis = next(readme)
|
||||
config.print_stdout("%s - %s", tempname, synopsis)
|
||||
|
||||
config.print_stdout("\nTemplates are used via the 'init' command, e.g.:")
|
||||
config.print_stdout("\n alembic init --template generic ./scripts")
|
||||
|
||||
|
||||
def init(config, directory, template="generic", package=False):
|
||||
"""Initialize a new scripts directory.
|
||||
|
||||
:param config: a :class:`.Config` object.
|
||||
|
||||
:param directory: string path of the target directory
|
||||
|
||||
:param template: string name of the migration environment template to
|
||||
use.
|
||||
|
||||
:param package: when True, write ``__init__.py`` files into the
|
||||
environment location as well as the versions/ location.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
|
||||
"""
|
||||
|
||||
if os.access(directory, os.F_OK) and os.listdir(directory):
|
||||
raise util.CommandError(
|
||||
"Directory %s already exists and is not empty" % directory
|
||||
)
|
||||
|
||||
template_dir = os.path.join(config.get_template_directory(), template)
|
||||
if not os.access(template_dir, os.F_OK):
|
||||
raise util.CommandError("No such template %r" % template)
|
||||
|
||||
if not os.access(directory, os.F_OK):
|
||||
util.status(
|
||||
"Creating directory %s" % os.path.abspath(directory),
|
||||
os.makedirs,
|
||||
directory,
|
||||
)
|
||||
|
||||
versions = os.path.join(directory, "versions")
|
||||
util.status(
|
||||
"Creating directory %s" % os.path.abspath(versions),
|
||||
os.makedirs,
|
||||
versions,
|
||||
)
|
||||
|
||||
script = ScriptDirectory(directory)
|
||||
|
||||
for file_ in os.listdir(template_dir):
|
||||
file_path = os.path.join(template_dir, file_)
|
||||
if file_ == "alembic.ini.mako":
|
||||
config_file = os.path.abspath(config.config_file_name)
|
||||
if os.access(config_file, os.F_OK):
|
||||
util.msg("File %s already exists, skipping" % config_file)
|
||||
else:
|
||||
script._generate_template(
|
||||
file_path, config_file, script_location=directory
|
||||
)
|
||||
elif os.path.isfile(file_path):
|
||||
output_file = os.path.join(directory, file_)
|
||||
script._copy_file(file_path, output_file)
|
||||
|
||||
if package:
|
||||
for path in [
|
||||
os.path.join(os.path.abspath(directory), "__init__.py"),
|
||||
os.path.join(os.path.abspath(versions), "__init__.py"),
|
||||
]:
|
||||
file_ = util.status("Adding %s" % path, open, path, "w")
|
||||
file_.close()
|
||||
|
||||
util.msg(
|
||||
"Please edit configuration/connection/logging "
|
||||
"settings in %r before proceeding." % config_file
|
||||
)
|
||||
|
||||
|
||||
def revision(
|
||||
config,
|
||||
message=None,
|
||||
autogenerate=False,
|
||||
sql=False,
|
||||
head="head",
|
||||
splice=False,
|
||||
branch_label=None,
|
||||
version_path=None,
|
||||
rev_id=None,
|
||||
depends_on=None,
|
||||
process_revision_directives=None,
|
||||
):
|
||||
"""Create a new revision file.
|
||||
|
||||
:param config: a :class:`.Config` object.
|
||||
|
||||
:param message: string message to apply to the revision; this is the
|
||||
``-m`` option to ``alembic revision``.
|
||||
|
||||
:param autogenerate: whether or not to autogenerate the script from
|
||||
the database; this is the ``--autogenerate`` option to
|
||||
``alembic revision``.
|
||||
|
||||
:param sql: whether to dump the script out as a SQL string; when specified,
|
||||
the script is dumped to stdout. This is the ``--sql`` option to
|
||||
``alembic revision``.
|
||||
|
||||
:param head: head revision to build the new revision upon as a parent;
|
||||
this is the ``--head`` option to ``alembic revision``.
|
||||
|
||||
:param splice: whether or not the new revision should be made into a
|
||||
new head of its own; is required when the given ``head`` is not itself
|
||||
a head. This is the ``--splice`` option to ``alembic revision``.
|
||||
|
||||
:param branch_label: string label to apply to the branch; this is the
|
||||
``--branch-label`` option to ``alembic revision``.
|
||||
|
||||
:param version_path: string symbol identifying a specific version path
|
||||
from the configuration; this is the ``--version-path`` option to
|
||||
``alembic revision``.
|
||||
|
||||
:param rev_id: optional revision identifier to use instead of having
|
||||
one generated; this is the ``--rev-id`` option to ``alembic revision``.
|
||||
|
||||
:param depends_on: optional list of "depends on" identifiers; this is the
|
||||
``--depends-on`` option to ``alembic revision``.
|
||||
|
||||
:param process_revision_directives: this is a callable that takes the
|
||||
same form as the callable described at
|
||||
:paramref:`.EnvironmentContext.configure.process_revision_directives`;
|
||||
will be applied to the structure generated by the revision process
|
||||
where it can be altered programmatically. Note that unlike all
|
||||
the other parameters, this option is only available via programmatic
|
||||
use of :func:`.command.revision`
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
script_directory = ScriptDirectory.from_config(config)
|
||||
|
||||
command_args = dict(
|
||||
message=message,
|
||||
autogenerate=autogenerate,
|
||||
sql=sql,
|
||||
head=head,
|
||||
splice=splice,
|
||||
branch_label=branch_label,
|
||||
version_path=version_path,
|
||||
rev_id=rev_id,
|
||||
depends_on=depends_on,
|
||||
)
|
||||
revision_context = autogen.RevisionContext(
|
||||
config,
|
||||
script_directory,
|
||||
command_args,
|
||||
process_revision_directives=process_revision_directives,
|
||||
)
|
||||
|
||||
environment = util.asbool(config.get_main_option("revision_environment"))
|
||||
|
||||
if autogenerate:
|
||||
environment = True
|
||||
|
||||
if sql:
|
||||
raise util.CommandError(
|
||||
"Using --sql with --autogenerate does not make any sense"
|
||||
)
|
||||
|
||||
def retrieve_migrations(rev, context):
|
||||
revision_context.run_autogenerate(rev, context)
|
||||
return []
|
||||
|
||||
elif environment:
|
||||
|
||||
def retrieve_migrations(rev, context):
|
||||
revision_context.run_no_autogenerate(rev, context)
|
||||
return []
|
||||
|
||||
elif sql:
|
||||
raise util.CommandError(
|
||||
"Using --sql with the revision command when "
|
||||
"revision_environment is not configured does not make any sense"
|
||||
)
|
||||
|
||||
if environment:
|
||||
with EnvironmentContext(
|
||||
config,
|
||||
script_directory,
|
||||
fn=retrieve_migrations,
|
||||
as_sql=sql,
|
||||
template_args=revision_context.template_args,
|
||||
revision_context=revision_context,
|
||||
):
|
||||
script_directory.run_env()
|
||||
|
||||
# the revision_context now has MigrationScript structure(s) present.
|
||||
# these could theoretically be further processed / rewritten *here*,
|
||||
# in addition to the hooks present within each run_migrations() call,
|
||||
# or at the end of env.py run_migrations_online().
|
||||
|
||||
scripts = [script for script in revision_context.generate_scripts()]
|
||||
if len(scripts) == 1:
|
||||
return scripts[0]
|
||||
else:
|
||||
return scripts
|
||||
|
||||
|
||||
def merge(config, revisions, message=None, branch_label=None, rev_id=None):
|
||||
"""Merge two revisions together. Creates a new migration file.
|
||||
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
:param config: a :class:`.Config` instance
|
||||
|
||||
:param message: string message to apply to the revision
|
||||
|
||||
:param branch_label: string label name to apply to the new revision
|
||||
|
||||
:param rev_id: hardcoded revision identifier instead of generating a new
|
||||
one.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`branches`
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
template_args = {
|
||||
"config": config # Let templates use config for
|
||||
# e.g. multiple databases
|
||||
}
|
||||
return script.generate_revision(
|
||||
rev_id or util.rev_id(),
|
||||
message,
|
||||
refresh=True,
|
||||
head=revisions,
|
||||
branch_labels=branch_label,
|
||||
**template_args
|
||||
)
|
||||
|
||||
|
||||
def upgrade(config, revision, sql=False, tag=None):
|
||||
"""Upgrade to a later version.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param revision: string revision target or range for --sql mode
|
||||
|
||||
:param sql: if True, use ``--sql`` mode
|
||||
|
||||
:param tag: an arbitrary "tag" that can be intercepted by custom
|
||||
``env.py`` scripts via the :meth:`.EnvironmentContext.get_tag_argument`
|
||||
method.
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
|
||||
starting_rev = None
|
||||
if ":" in revision:
|
||||
if not sql:
|
||||
raise util.CommandError("Range revision not allowed")
|
||||
starting_rev, revision = revision.split(":", 2)
|
||||
|
||||
def upgrade(rev, context):
|
||||
return script._upgrade_revs(revision, rev)
|
||||
|
||||
with EnvironmentContext(
|
||||
config,
|
||||
script,
|
||||
fn=upgrade,
|
||||
as_sql=sql,
|
||||
starting_rev=starting_rev,
|
||||
destination_rev=revision,
|
||||
tag=tag,
|
||||
):
|
||||
script.run_env()
|
||||
|
||||
|
||||
def downgrade(config, revision, sql=False, tag=None):
|
||||
"""Revert to a previous version.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param revision: string revision target or range for --sql mode
|
||||
|
||||
:param sql: if True, use ``--sql`` mode
|
||||
|
||||
:param tag: an arbitrary "tag" that can be intercepted by custom
|
||||
``env.py`` scripts via the :meth:`.EnvironmentContext.get_tag_argument`
|
||||
method.
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
starting_rev = None
|
||||
if ":" in revision:
|
||||
if not sql:
|
||||
raise util.CommandError("Range revision not allowed")
|
||||
starting_rev, revision = revision.split(":", 2)
|
||||
elif sql:
|
||||
raise util.CommandError(
|
||||
"downgrade with --sql requires <fromrev>:<torev>"
|
||||
)
|
||||
|
||||
def downgrade(rev, context):
|
||||
return script._downgrade_revs(revision, rev)
|
||||
|
||||
with EnvironmentContext(
|
||||
config,
|
||||
script,
|
||||
fn=downgrade,
|
||||
as_sql=sql,
|
||||
starting_rev=starting_rev,
|
||||
destination_rev=revision,
|
||||
tag=tag,
|
||||
):
|
||||
script.run_env()
|
||||
|
||||
|
||||
def show(config, rev):
|
||||
"""Show the revision(s) denoted by the given symbol.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param revision: string revision target
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
|
||||
if rev == "current":
|
||||
|
||||
def show_current(rev, context):
|
||||
for sc in script.get_revisions(rev):
|
||||
config.print_stdout(sc.log_entry)
|
||||
return []
|
||||
|
||||
with EnvironmentContext(config, script, fn=show_current):
|
||||
script.run_env()
|
||||
else:
|
||||
for sc in script.get_revisions(rev):
|
||||
config.print_stdout(sc.log_entry)
|
||||
|
||||
|
||||
def history(config, rev_range=None, verbose=False, indicate_current=False):
|
||||
"""List changeset scripts in chronological order.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param rev_range: string revision range
|
||||
|
||||
:param verbose: output in verbose mode.
|
||||
|
||||
:param indicate_current: indicate current revision.
|
||||
|
||||
..versionadded:: 0.9.9
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
if rev_range is not None:
|
||||
if ":" not in rev_range:
|
||||
raise util.CommandError(
|
||||
"History range requires [start]:[end], " "[start]:, or :[end]"
|
||||
)
|
||||
base, head = rev_range.strip().split(":")
|
||||
else:
|
||||
base = head = None
|
||||
|
||||
environment = (
|
||||
util.asbool(config.get_main_option("revision_environment"))
|
||||
or indicate_current
|
||||
)
|
||||
|
||||
def _display_history(config, script, base, head, currents=()):
|
||||
for sc in script.walk_revisions(
|
||||
base=base or "base", head=head or "heads"
|
||||
):
|
||||
|
||||
if indicate_current:
|
||||
sc._db_current_indicator = sc.revision in currents
|
||||
|
||||
config.print_stdout(
|
||||
sc.cmd_format(
|
||||
verbose=verbose,
|
||||
include_branches=True,
|
||||
include_doc=True,
|
||||
include_parents=True,
|
||||
)
|
||||
)
|
||||
|
||||
def _display_history_w_current(config, script, base, head):
|
||||
def _display_current_history(rev, context):
|
||||
if head == "current":
|
||||
_display_history(config, script, base, rev, rev)
|
||||
elif base == "current":
|
||||
_display_history(config, script, rev, head, rev)
|
||||
else:
|
||||
_display_history(config, script, base, head, rev)
|
||||
return []
|
||||
|
||||
with EnvironmentContext(config, script, fn=_display_current_history):
|
||||
script.run_env()
|
||||
|
||||
if base == "current" or head == "current" or environment:
|
||||
_display_history_w_current(config, script, base, head)
|
||||
else:
|
||||
_display_history(config, script, base, head)
|
||||
|
||||
|
||||
def heads(config, verbose=False, resolve_dependencies=False):
|
||||
"""Show current available heads in the script directory.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param verbose: output in verbose mode.
|
||||
|
||||
:param resolve_dependencies: treat dependency version as down revisions.
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
if resolve_dependencies:
|
||||
heads = script.get_revisions("heads")
|
||||
else:
|
||||
heads = script.get_revisions(script.get_heads())
|
||||
|
||||
for rev in heads:
|
||||
config.print_stdout(
|
||||
rev.cmd_format(
|
||||
verbose, include_branches=True, tree_indicators=False
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def branches(config, verbose=False):
|
||||
"""Show current branch points.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param verbose: output in verbose mode.
|
||||
|
||||
"""
|
||||
script = ScriptDirectory.from_config(config)
|
||||
for sc in script.walk_revisions():
|
||||
if sc.is_branch_point:
|
||||
config.print_stdout(
|
||||
"%s\n%s\n",
|
||||
sc.cmd_format(verbose, include_branches=True),
|
||||
"\n".join(
|
||||
"%s -> %s"
|
||||
% (
|
||||
" " * len(str(sc.revision)),
|
||||
rev_obj.cmd_format(
|
||||
False, include_branches=True, include_doc=verbose
|
||||
),
|
||||
)
|
||||
for rev_obj in (
|
||||
script.get_revision(rev) for rev in sc.nextrev
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def current(config, verbose=False, head_only=False):
|
||||
"""Display the current revision for a database.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param verbose: output in verbose mode.
|
||||
|
||||
:param head_only: deprecated; use ``verbose`` for additional output.
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
|
||||
if head_only:
|
||||
util.warn("--head-only is deprecated", stacklevel=3)
|
||||
|
||||
def display_version(rev, context):
|
||||
if verbose:
|
||||
config.print_stdout(
|
||||
"Current revision(s) for %s:",
|
||||
util.obfuscate_url_pw(context.connection.engine.url),
|
||||
)
|
||||
for rev in script.get_all_current(rev):
|
||||
config.print_stdout(rev.cmd_format(verbose))
|
||||
|
||||
return []
|
||||
|
||||
with EnvironmentContext(config, script, fn=display_version):
|
||||
script.run_env()
|
||||
|
||||
|
||||
def stamp(config, revision, sql=False, tag=None, purge=False):
|
||||
"""'stamp' the revision table with the given revision; don't
|
||||
run any migrations.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param revision: target revision or list of revisions. May be a list
|
||||
to indicate stamping of multiple branch heads.
|
||||
|
||||
.. note:: this parameter is called "revisions" in the command line
|
||||
interface.
|
||||
|
||||
.. versionchanged:: 1.2 The revision may be a single revision or
|
||||
list of revisions when stamping multiple branch heads.
|
||||
|
||||
:param sql: use ``--sql`` mode
|
||||
|
||||
:param tag: an arbitrary "tag" that can be intercepted by custom
|
||||
``env.py`` scripts via the :class:`.EnvironmentContext.get_tag_argument`
|
||||
method.
|
||||
|
||||
:param purge: delete all entries in the version table before stamping.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
|
||||
if sql:
|
||||
destination_revs = []
|
||||
starting_rev = None
|
||||
for _revision in util.to_list(revision):
|
||||
if ":" in _revision:
|
||||
srev, _revision = _revision.split(":", 2)
|
||||
|
||||
if starting_rev != srev:
|
||||
if starting_rev is None:
|
||||
starting_rev = srev
|
||||
else:
|
||||
raise util.CommandError(
|
||||
"Stamp operation with --sql only supports a "
|
||||
"single starting revision at a time"
|
||||
)
|
||||
destination_revs.append(_revision)
|
||||
else:
|
||||
destination_revs = util.to_list(revision)
|
||||
|
||||
def do_stamp(rev, context):
|
||||
return script._stamp_revs(util.to_tuple(destination_revs), rev)
|
||||
|
||||
with EnvironmentContext(
|
||||
config,
|
||||
script,
|
||||
fn=do_stamp,
|
||||
as_sql=sql,
|
||||
starting_rev=starting_rev if sql else None,
|
||||
destination_rev=util.to_tuple(destination_revs),
|
||||
tag=tag,
|
||||
purge=purge,
|
||||
):
|
||||
script.run_env()
|
||||
|
||||
|
||||
def edit(config, rev):
|
||||
"""Edit revision script(s) using $EDITOR.
|
||||
|
||||
:param config: a :class:`.Config` instance.
|
||||
|
||||
:param rev: target revision.
|
||||
|
||||
"""
|
||||
|
||||
script = ScriptDirectory.from_config(config)
|
||||
|
||||
if rev == "current":
|
||||
|
||||
def edit_current(rev, context):
|
||||
if not rev:
|
||||
raise util.CommandError("No current revisions")
|
||||
for sc in script.get_revisions(rev):
|
||||
util.edit(sc.path)
|
||||
return []
|
||||
|
||||
with EnvironmentContext(config, script, fn=edit_current):
|
||||
script.run_env()
|
||||
else:
|
||||
revs = script.get_revisions(rev)
|
||||
if not revs:
|
||||
raise util.CommandError(
|
||||
"No revision files indicated by symbol '%s'" % rev
|
||||
)
|
||||
for sc in revs:
|
||||
util.edit(sc.path)
|
@ -1,581 +0,0 @@
|
||||
from argparse import ArgumentParser
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
|
||||
from . import command
|
||||
from . import util
|
||||
from .util import compat
|
||||
from .util.compat import SafeConfigParser
|
||||
|
||||
|
||||
class Config(object):
|
||||
|
||||
r"""Represent an Alembic configuration.
|
||||
|
||||
Within an ``env.py`` script, this is available
|
||||
via the :attr:`.EnvironmentContext.config` attribute,
|
||||
which in turn is available at ``alembic.context``::
|
||||
|
||||
from alembic import context
|
||||
|
||||
some_param = context.config.get_main_option("my option")
|
||||
|
||||
When invoking Alembic programatically, a new
|
||||
:class:`.Config` can be created by passing
|
||||
the name of an .ini file to the constructor::
|
||||
|
||||
from alembic.config import Config
|
||||
alembic_cfg = Config("/path/to/yourapp/alembic.ini")
|
||||
|
||||
With a :class:`.Config` object, you can then
|
||||
run Alembic commands programmatically using the directives
|
||||
in :mod:`alembic.command`.
|
||||
|
||||
The :class:`.Config` object can also be constructed without
|
||||
a filename. Values can be set programmatically, and
|
||||
new sections will be created as needed::
|
||||
|
||||
from alembic.config import Config
|
||||
alembic_cfg = Config()
|
||||
alembic_cfg.set_main_option("script_location", "myapp:migrations")
|
||||
alembic_cfg.set_main_option("sqlalchemy.url", "postgresql://foo/bar")
|
||||
alembic_cfg.set_section_option("mysection", "foo", "bar")
|
||||
|
||||
.. warning::
|
||||
|
||||
When using programmatic configuration, make sure the
|
||||
``env.py`` file in use is compatible with the target configuration;
|
||||
including that the call to Python ``logging.fileConfig()`` is
|
||||
omitted if the programmatic configuration doesn't actually include
|
||||
logging directives.
|
||||
|
||||
For passing non-string values to environments, such as connections and
|
||||
engines, use the :attr:`.Config.attributes` dictionary::
|
||||
|
||||
with engine.begin() as connection:
|
||||
alembic_cfg.attributes['connection'] = connection
|
||||
command.upgrade(alembic_cfg, "head")
|
||||
|
||||
:param file\_: name of the .ini file to open.
|
||||
:param ini_section: name of the main Alembic section within the
|
||||
.ini file
|
||||
:param output_buffer: optional file-like input buffer which
|
||||
will be passed to the :class:`.MigrationContext` - used to redirect
|
||||
the output of "offline generation" when using Alembic programmatically.
|
||||
:param stdout: buffer where the "print" output of commands will be sent.
|
||||
Defaults to ``sys.stdout``.
|
||||
|
||||
.. versionadded:: 0.4
|
||||
|
||||
:param config_args: A dictionary of keys and values that will be used
|
||||
for substitution in the alembic config file. The dictionary as given
|
||||
is **copied** to a new one, stored locally as the attribute
|
||||
``.config_args``. When the :attr:`.Config.file_config` attribute is
|
||||
first invoked, the replacement variable ``here`` will be added to this
|
||||
dictionary before the dictionary is passed to ``SafeConfigParser()``
|
||||
to parse the .ini file.
|
||||
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
:param attributes: optional dictionary of arbitrary Python keys/values,
|
||||
which will be populated into the :attr:`.Config.attributes` dictionary.
|
||||
|
||||
.. versionadded:: 0.7.5
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`connection_sharing`
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_=None,
|
||||
ini_section="alembic",
|
||||
output_buffer=None,
|
||||
stdout=sys.stdout,
|
||||
cmd_opts=None,
|
||||
config_args=util.immutabledict(),
|
||||
attributes=None,
|
||||
):
|
||||
"""Construct a new :class:`.Config`
|
||||
|
||||
"""
|
||||
self.config_file_name = file_
|
||||
self.config_ini_section = ini_section
|
||||
self.output_buffer = output_buffer
|
||||
self.stdout = stdout
|
||||
self.cmd_opts = cmd_opts
|
||||
self.config_args = dict(config_args)
|
||||
if attributes:
|
||||
self.attributes.update(attributes)
|
||||
|
||||
cmd_opts = None
|
||||
"""The command-line options passed to the ``alembic`` script.
|
||||
|
||||
Within an ``env.py`` script this can be accessed via the
|
||||
:attr:`.EnvironmentContext.config` attribute.
|
||||
|
||||
.. versionadded:: 0.6.0
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`.EnvironmentContext.get_x_argument`
|
||||
|
||||
"""
|
||||
|
||||
config_file_name = None
|
||||
"""Filesystem path to the .ini file in use."""
|
||||
|
||||
config_ini_section = None
|
||||
"""Name of the config file section to read basic configuration
|
||||
from. Defaults to ``alembic``, that is the ``[alembic]`` section
|
||||
of the .ini file. This value is modified using the ``-n/--name``
|
||||
option to the Alembic runnier.
|
||||
|
||||
"""
|
||||
|
||||
@util.memoized_property
|
||||
def attributes(self):
|
||||
"""A Python dictionary for storage of additional state.
|
||||
|
||||
|
||||
This is a utility dictionary which can include not just strings but
|
||||
engines, connections, schema objects, or anything else.
|
||||
Use this to pass objects into an env.py script, such as passing
|
||||
a :class:`sqlalchemy.engine.base.Connection` when calling
|
||||
commands from :mod:`alembic.command` programmatically.
|
||||
|
||||
.. versionadded:: 0.7.5
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`connection_sharing`
|
||||
|
||||
:paramref:`.Config.attributes`
|
||||
|
||||
"""
|
||||
return {}
|
||||
|
||||
def print_stdout(self, text, *arg):
|
||||
"""Render a message to standard out.
|
||||
|
||||
When :meth:`.Config.print_stdout` is called with additional args
|
||||
those arguments will formatted against the provided text,
|
||||
otherwise we simply output the provided text verbatim.
|
||||
|
||||
e.g.::
|
||||
|
||||
>>> config.print_stdout('Some text %s', 'arg')
|
||||
Some Text arg
|
||||
|
||||
"""
|
||||
|
||||
if arg:
|
||||
output = compat.text_type(text) % arg
|
||||
else:
|
||||
output = compat.text_type(text)
|
||||
|
||||
util.write_outstream(self.stdout, output, "\n")
|
||||
|
||||
@util.memoized_property
|
||||
def file_config(self):
|
||||
"""Return the underlying ``ConfigParser`` object.
|
||||
|
||||
Direct access to the .ini file is available here,
|
||||
though the :meth:`.Config.get_section` and
|
||||
:meth:`.Config.get_main_option`
|
||||
methods provide a possibly simpler interface.
|
||||
|
||||
"""
|
||||
|
||||
if self.config_file_name:
|
||||
here = os.path.abspath(os.path.dirname(self.config_file_name))
|
||||
else:
|
||||
here = ""
|
||||
self.config_args["here"] = here
|
||||
file_config = SafeConfigParser(self.config_args)
|
||||
if self.config_file_name:
|
||||
file_config.read([self.config_file_name])
|
||||
else:
|
||||
file_config.add_section(self.config_ini_section)
|
||||
return file_config
|
||||
|
||||
def get_template_directory(self):
|
||||
"""Return the directory where Alembic setup templates are found.
|
||||
|
||||
This method is used by the alembic ``init`` and ``list_templates``
|
||||
commands.
|
||||
|
||||
"""
|
||||
import alembic
|
||||
|
||||
package_dir = os.path.abspath(os.path.dirname(alembic.__file__))
|
||||
return os.path.join(package_dir, "templates")
|
||||
|
||||
def get_section(self, name, default=None):
|
||||
"""Return all the configuration options from a given .ini file section
|
||||
as a dictionary.
|
||||
|
||||
"""
|
||||
if not self.file_config.has_section(name):
|
||||
return default
|
||||
|
||||
return dict(self.file_config.items(name))
|
||||
|
||||
def set_main_option(self, name, value):
|
||||
"""Set an option programmatically within the 'main' section.
|
||||
|
||||
This overrides whatever was in the .ini file.
|
||||
|
||||
:param name: name of the value
|
||||
|
||||
:param value: the value. Note that this value is passed to
|
||||
``ConfigParser.set``, which supports variable interpolation using
|
||||
pyformat (e.g. ``%(some_value)s``). A raw percent sign not part of
|
||||
an interpolation symbol must therefore be escaped, e.g. ``%%``.
|
||||
The given value may refer to another value already in the file
|
||||
using the interpolation format.
|
||||
|
||||
"""
|
||||
self.set_section_option(self.config_ini_section, name, value)
|
||||
|
||||
def remove_main_option(self, name):
|
||||
self.file_config.remove_option(self.config_ini_section, name)
|
||||
|
||||
def set_section_option(self, section, name, value):
|
||||
"""Set an option programmatically within the given section.
|
||||
|
||||
The section is created if it doesn't exist already.
|
||||
The value here will override whatever was in the .ini
|
||||
file.
|
||||
|
||||
:param section: name of the section
|
||||
|
||||
:param name: name of the value
|
||||
|
||||
:param value: the value. Note that this value is passed to
|
||||
``ConfigParser.set``, which supports variable interpolation using
|
||||
pyformat (e.g. ``%(some_value)s``). A raw percent sign not part of
|
||||
an interpolation symbol must therefore be escaped, e.g. ``%%``.
|
||||
The given value may refer to another value already in the file
|
||||
using the interpolation format.
|
||||
|
||||
"""
|
||||
|
||||
if not self.file_config.has_section(section):
|
||||
self.file_config.add_section(section)
|
||||
self.file_config.set(section, name, value)
|
||||
|
||||
def get_section_option(self, section, name, default=None):
|
||||
"""Return an option from the given section of the .ini file.
|
||||
|
||||
"""
|
||||
if not self.file_config.has_section(section):
|
||||
raise util.CommandError(
|
||||
"No config file %r found, or file has no "
|
||||
"'[%s]' section" % (self.config_file_name, section)
|
||||
)
|
||||
if self.file_config.has_option(section, name):
|
||||
return self.file_config.get(section, name)
|
||||
else:
|
||||
return default
|
||||
|
||||
def get_main_option(self, name, default=None):
|
||||
"""Return an option from the 'main' section of the .ini file.
|
||||
|
||||
This defaults to being a key from the ``[alembic]``
|
||||
section, unless the ``-n/--name`` flag were used to
|
||||
indicate a different section.
|
||||
|
||||
"""
|
||||
return self.get_section_option(self.config_ini_section, name, default)
|
||||
|
||||
|
||||
class CommandLine(object):
|
||||
def __init__(self, prog=None):
|
||||
self._generate_args(prog)
|
||||
|
||||
def _generate_args(self, prog):
|
||||
def add_options(fn, parser, positional, kwargs):
|
||||
kwargs_opts = {
|
||||
"template": (
|
||||
"-t",
|
||||
"--template",
|
||||
dict(
|
||||
default="generic",
|
||||
type=str,
|
||||
help="Setup template for use with 'init'",
|
||||
),
|
||||
),
|
||||
"message": (
|
||||
"-m",
|
||||
"--message",
|
||||
dict(
|
||||
type=str, help="Message string to use with 'revision'"
|
||||
),
|
||||
),
|
||||
"sql": (
|
||||
"--sql",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Don't emit SQL to database - dump to "
|
||||
"standard output/file instead. See docs on "
|
||||
"offline mode.",
|
||||
),
|
||||
),
|
||||
"tag": (
|
||||
"--tag",
|
||||
dict(
|
||||
type=str,
|
||||
help="Arbitrary 'tag' name - can be used by "
|
||||
"custom env.py scripts.",
|
||||
),
|
||||
),
|
||||
"head": (
|
||||
"--head",
|
||||
dict(
|
||||
type=str,
|
||||
help="Specify head revision or <branchname>@head "
|
||||
"to base new revision on.",
|
||||
),
|
||||
),
|
||||
"splice": (
|
||||
"--splice",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Allow a non-head revision as the "
|
||||
"'head' to splice onto",
|
||||
),
|
||||
),
|
||||
"depends_on": (
|
||||
"--depends-on",
|
||||
dict(
|
||||
action="append",
|
||||
help="Specify one or more revision identifiers "
|
||||
"which this revision should depend on.",
|
||||
),
|
||||
),
|
||||
"rev_id": (
|
||||
"--rev-id",
|
||||
dict(
|
||||
type=str,
|
||||
help="Specify a hardcoded revision id instead of "
|
||||
"generating one",
|
||||
),
|
||||
),
|
||||
"version_path": (
|
||||
"--version-path",
|
||||
dict(
|
||||
type=str,
|
||||
help="Specify specific path from config for "
|
||||
"version file",
|
||||
),
|
||||
),
|
||||
"branch_label": (
|
||||
"--branch-label",
|
||||
dict(
|
||||
type=str,
|
||||
help="Specify a branch label to apply to the "
|
||||
"new revision",
|
||||
),
|
||||
),
|
||||
"verbose": (
|
||||
"-v",
|
||||
"--verbose",
|
||||
dict(action="store_true", help="Use more verbose output"),
|
||||
),
|
||||
"resolve_dependencies": (
|
||||
"--resolve-dependencies",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Treat dependency versions as down revisions",
|
||||
),
|
||||
),
|
||||
"autogenerate": (
|
||||
"--autogenerate",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Populate revision script with candidate "
|
||||
"migration operations, based on comparison "
|
||||
"of database to model.",
|
||||
),
|
||||
),
|
||||
"head_only": (
|
||||
"--head-only",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Deprecated. Use --verbose for "
|
||||
"additional output",
|
||||
),
|
||||
),
|
||||
"rev_range": (
|
||||
"-r",
|
||||
"--rev-range",
|
||||
dict(
|
||||
action="store",
|
||||
help="Specify a revision range; "
|
||||
"format is [start]:[end]",
|
||||
),
|
||||
),
|
||||
"indicate_current": (
|
||||
"-i",
|
||||
"--indicate-current",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Indicate the current revision",
|
||||
),
|
||||
),
|
||||
"purge": (
|
||||
"--purge",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Unconditionally erase the version table "
|
||||
"before stamping",
|
||||
),
|
||||
),
|
||||
"package": (
|
||||
"--package",
|
||||
dict(
|
||||
action="store_true",
|
||||
help="Write empty __init__.py files to the "
|
||||
"environment and version locations",
|
||||
),
|
||||
),
|
||||
}
|
||||
positional_help = {
|
||||
"directory": "location of scripts directory",
|
||||
"revision": "revision identifier",
|
||||
"revisions": "one or more revisions, or 'heads' for all heads",
|
||||
}
|
||||
for arg in kwargs:
|
||||
if arg in kwargs_opts:
|
||||
args = kwargs_opts[arg]
|
||||
args, kw = args[0:-1], args[-1]
|
||||
parser.add_argument(*args, **kw)
|
||||
|
||||
for arg in positional:
|
||||
if (
|
||||
arg == "revisions"
|
||||
or fn in positional_translations
|
||||
and positional_translations[fn][arg] == "revisions"
|
||||
):
|
||||
subparser.add_argument(
|
||||
"revisions",
|
||||
nargs="+",
|
||||
help=positional_help.get("revisions"),
|
||||
)
|
||||
else:
|
||||
subparser.add_argument(arg, help=positional_help.get(arg))
|
||||
|
||||
parser = ArgumentParser(prog=prog)
|
||||
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--config",
|
||||
type=str,
|
||||
default=os.environ.get("ALEMBIC_CONFIG", "alembic.ini"),
|
||||
help="Alternate config file; defaults to value of "
|
||||
'ALEMBIC_CONFIG environment variable, or "alembic.ini"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--name",
|
||||
type=str,
|
||||
default="alembic",
|
||||
help="Name of section in .ini file to " "use for Alembic config",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-x",
|
||||
action="append",
|
||||
help="Additional arguments consumed by "
|
||||
"custom env.py scripts, e.g. -x "
|
||||
"setting1=somesetting -x setting2=somesetting",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--raiseerr",
|
||||
action="store_true",
|
||||
help="Raise a full stack trace on error",
|
||||
)
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
positional_translations = {command.stamp: {"revision": "revisions"}}
|
||||
|
||||
for fn in [getattr(command, n) for n in dir(command)]:
|
||||
if (
|
||||
inspect.isfunction(fn)
|
||||
and fn.__name__[0] != "_"
|
||||
and fn.__module__ == "alembic.command"
|
||||
):
|
||||
|
||||
spec = compat.inspect_getargspec(fn)
|
||||
if spec[3]:
|
||||
positional = spec[0][1 : -len(spec[3])]
|
||||
kwarg = spec[0][-len(spec[3]) :]
|
||||
else:
|
||||
positional = spec[0][1:]
|
||||
kwarg = []
|
||||
|
||||
if fn in positional_translations:
|
||||
positional = [
|
||||
positional_translations[fn].get(name, name)
|
||||
for name in positional
|
||||
]
|
||||
|
||||
# parse first line(s) of helptext without a line break
|
||||
help_ = fn.__doc__
|
||||
if help_:
|
||||
help_text = []
|
||||
for line in help_.split("\n"):
|
||||
if not line.strip():
|
||||
break
|
||||
else:
|
||||
help_text.append(line.strip())
|
||||
else:
|
||||
help_text = ""
|
||||
subparser = subparsers.add_parser(
|
||||
fn.__name__, help=" ".join(help_text)
|
||||
)
|
||||
add_options(fn, subparser, positional, kwarg)
|
||||
subparser.set_defaults(cmd=(fn, positional, kwarg))
|
||||
self.parser = parser
|
||||
|
||||
def run_cmd(self, config, options):
|
||||
fn, positional, kwarg = options.cmd
|
||||
|
||||
try:
|
||||
fn(
|
||||
config,
|
||||
*[getattr(options, k, None) for k in positional],
|
||||
**dict((k, getattr(options, k, None)) for k in kwarg)
|
||||
)
|
||||
except util.CommandError as e:
|
||||
if options.raiseerr:
|
||||
raise
|
||||
else:
|
||||
util.err(str(e))
|
||||
|
||||
def main(self, argv=None):
|
||||
options = self.parser.parse_args(argv)
|
||||
if not hasattr(options, "cmd"):
|
||||
# see http://bugs.python.org/issue9253, argparse
|
||||
# behavior changed incompatibly in py3.3
|
||||
self.parser.error("too few arguments")
|
||||
else:
|
||||
cfg = Config(
|
||||
file_=options.config,
|
||||
ini_section=options.name,
|
||||
cmd_opts=options,
|
||||
)
|
||||
self.run_cmd(cfg, options)
|
||||
|
||||
|
||||
def main(argv=None, prog=None, **kwargs):
|
||||
"""The console runner function for Alembic."""
|
||||
|
||||
CommandLine(prog=prog).main(argv=argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,5 +0,0 @@
|
||||
from .runtime.environment import EnvironmentContext
|
||||
|
||||
# create proxy functions for
|
||||
# each method on the EnvironmentContext class.
|
||||
EnvironmentContext.create_module_class_proxy(globals(), locals())
|
@ -1,6 +0,0 @@
|
||||
from . import mssql # noqa
|
||||
from . import mysql # noqa
|
||||
from . import oracle # noqa
|
||||
from . import postgresql # noqa
|
||||
from . import sqlite # noqa
|
||||
from .impl import DefaultImpl # noqa
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue