aboutsummaryrefslogtreecommitdiff
path: root/wqflask
diff options
context:
space:
mode:
authorMuriithi Frederick Muriuki2018-03-31 14:45:17 +0300
committerMuriithi Frederick Muriuki2018-03-31 14:45:17 +0300
commit31747256e466456cc88aac60780836a6534f18cd (patch)
treea7b371e4ec217ffb37594e15f5e603ae28511dc2 /wqflask
parentcfce6d80be4fb38573c37d1943db2687d54cf2fc (diff)
parent5424741a4a126bfd5f04df7cbcdc30b4e1376b86 (diff)
downloadgenenetwork2-31747256e466456cc88aac60780836a6534f18cd.tar.gz
Merge branch 'testing' of https://github.com/genenetwork/genenetwork2 into testing
* Fix conflicts
Diffstat (limited to 'wqflask')
-rw-r--r--wqflask/flask_security/__init__.py25
-rw-r--r--wqflask/flask_security/changeable.py45
-rw-r--r--wqflask/flask_security/confirmable.py83
-rw-r--r--wqflask/flask_security/core.py382
-rw-r--r--wqflask/flask_security/datastore.py261
-rw-r--r--wqflask/flask_security/decorators.py207
-rw-r--r--wqflask/flask_security/forms.py286
-rw-r--r--wqflask/flask_security/passwordless.py59
-rw-r--r--wqflask/flask_security/recoverable.py80
-rw-r--r--wqflask/flask_security/registerable.py44
-rw-r--r--wqflask/flask_security/script.py130
-rw-r--r--wqflask/flask_security/signals.py29
-rw-r--r--wqflask/flask_security/templates/.DS_Storebin6148 -> 0 bytes
-rw-r--r--wqflask/flask_security/templates/security/.DS_Storebin6148 -> 0 bytes
-rw-r--r--wqflask/flask_security/templates/security/_macros.html16
-rw-r--r--wqflask/flask_security/templates/security/_menu.html15
-rw-r--r--wqflask/flask_security/templates/security/_messages.html9
-rw-r--r--wqflask/flask_security/templates/security/change_password.html11
-rw-r--r--wqflask/flask_security/templates/security/email/change_notice.html4
-rw-r--r--wqflask/flask_security/templates/security/email/change_notice.txt5
-rw-r--r--wqflask/flask_security/templates/security/email/confirmation_instructions.html3
-rw-r--r--wqflask/flask_security/templates/security/email/confirmation_instructions.txt3
-rw-r--r--wqflask/flask_security/templates/security/email/login_instructions.html5
-rw-r--r--wqflask/flask_security/templates/security/email/login_instructions.txt5
-rw-r--r--wqflask/flask_security/templates/security/email/reset_instructions.html1
-rw-r--r--wqflask/flask_security/templates/security/email/reset_instructions.txt3
-rw-r--r--wqflask/flask_security/templates/security/email/reset_notice.html1
-rw-r--r--wqflask/flask_security/templates/security/email/reset_notice.txt1
-rw-r--r--wqflask/flask_security/templates/security/email/welcome.html7
-rw-r--r--wqflask/flask_security/templates/security/email/welcome.txt7
-rw-r--r--wqflask/flask_security/templates/security/forgot_password.html9
-rw-r--r--wqflask/flask_security/templates/security/login_user.html12
-rw-r--r--wqflask/flask_security/templates/security/register_user.html13
-rw-r--r--wqflask/flask_security/templates/security/reset_password.html10
-rw-r--r--wqflask/flask_security/templates/security/send_confirmation.html9
-rw-r--r--wqflask/flask_security/templates/security/send_login.html9
-rw-r--r--wqflask/flask_security/utils.py379
-rw-r--r--wqflask/flask_security/views.py359
-rw-r--r--wqflask/run_gunicorn.py6
-rw-r--r--wqflask/runserver.py17
-rw-r--r--wqflask/utility/elasticsearch_tools.py5
-rw-r--r--wqflask/utility/startup_config.py39
-rw-r--r--wqflask/utility/tools.py34
-rw-r--r--wqflask/utility/type_checking.py42
-rw-r--r--wqflask/wqflask/__init__.py4
-rw-r--r--wqflask/wqflask/collect.py51
-rw-r--r--wqflask/wqflask/correlation/show_corr_results.py116
-rw-r--r--wqflask/wqflask/correlation_matrix/show_corr_matrix.py9
-rw-r--r--wqflask/wqflask/gsearch.py6
-rw-r--r--wqflask/wqflask/marker_regression/gemma_mapping.py22
-rw-r--r--wqflask/wqflask/marker_regression/marker_regression.py1
-rw-r--r--wqflask/wqflask/marker_regression/marker_regression_gn1.py2
-rw-r--r--wqflask/wqflask/marker_regression/qtlreaper_mapping.py17
-rw-r--r--wqflask/wqflask/search_results.py23
-rw-r--r--wqflask/wqflask/static/dbdoc/TODO.md1
-rw-r--r--wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2.js130
-rw-r--r--wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2_sr.js137
-rw-r--r--wqflask/wqflask/static/new/javascript/get_covariates_from_collection.js5
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.js3
-rw-r--r--wqflask/wqflask/templates/collections/list.html12
-rw-r--r--wqflask/wqflask/templates/corr_scatterplot.html176
-rw-r--r--wqflask/wqflask/templates/correlation_matrix.html3
-rw-r--r--wqflask/wqflask/templates/correlation_page.html28
-rw-r--r--wqflask/wqflask/templates/empty_collection.html15
-rw-r--r--wqflask/wqflask/templates/new_security/login_user.html10
-rw-r--r--wqflask/wqflask/templates/show_trait_calculate_correlations.html106
-rw-r--r--wqflask/wqflask/templates/show_trait_mapping_tools.html232
-rw-r--r--wqflask/wqflask/user_manager.py52
-rw-r--r--wqflask/wqflask/views.py75
69 files changed, 708 insertions, 3198 deletions
diff --git a/wqflask/flask_security/__init__.py b/wqflask/flask_security/__init__.py
deleted file mode 100644
index 81e6c89e..00000000
--- a/wqflask/flask_security/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security
- ~~~~~~~~~~~~~~~~~~
-
- Flask-Security is a Flask extension that aims to add quick and simple
- security via Flask-Login, Flask-Principal, Flask-WTF, and passlib.
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-__version__ = '1.6.0'
-
-from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
-from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
-from .decorators import auth_token_required, http_auth_required, \
- login_required, roles_accepted, roles_required
-from .forms import ForgotPasswordForm, LoginForm, RegisterForm, \
- ResetPasswordForm, PasswordlessLoginForm, ConfirmRegisterForm
-from .signals import confirm_instructions_sent, password_reset, \
- reset_password_instructions_sent, user_confirmed, user_registered
-from .utils import login_user, logout_user, url_for_security
-
-print "Using our own flask.ext.security" \ No newline at end of file
diff --git a/wqflask/flask_security/changeable.py b/wqflask/flask_security/changeable.py
deleted file mode 100644
index 4447b655..00000000
--- a/wqflask/flask_security/changeable.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.changeable
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security recoverable module
-
- :copyright: (c) 2012 by Matt Wright.
- :author: Eskil Heyn Olsen
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import current_app as app, request
-from werkzeug.local import LocalProxy
-
-from .signals import password_changed
-from .utils import send_mail, encrypt_password, url_for_security, \
- config_value
-
-
-# Convenient references
-_security = LocalProxy(lambda: app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def send_password_changed_notice(user):
- """Sends the password changed notice email for the specified user.
-
- :param user: The user to send the notice to
- """
- send_mail(config_value('EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE'), user.email,
- 'change_notice', user=user)
-
-
-def change_user_password(user, password):
- """Change the specified user's password
-
- :param user: The user to change_password
- :param password: The unencrypted new password
- """
- user.password = encrypt_password(password)
- _datastore.put(user)
- send_password_changed_notice(user)
- password_changed.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/confirmable.py b/wqflask/flask_security/confirmable.py
deleted file mode 100644
index a7caf6cd..00000000
--- a/wqflask/flask_security/confirmable.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.confirmable
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security confirmable module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from datetime import datetime
-
-from flask import current_app as app, request
-from werkzeug.local import LocalProxy
-
-from .utils import send_mail, md5, url_for_security, get_token_status,\
- config_value
-from .signals import user_confirmed, confirm_instructions_sent
-
-
-# Convenient references
-_security = LocalProxy(lambda: app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def generate_confirmation_link(user):
- token = generate_confirmation_token(user)
- url = url_for_security('confirm_email', token=token)
- return request.url_root[:-1] + url, token
-
-
-def send_confirmation_instructions(user):
- """Sends the confirmation instructions email for the specified user.
-
- :param user: The user to send the instructions to
- :param token: The confirmation token
- """
-
- confirmation_link, token = generate_confirmation_link(user)
-
- send_mail(config_value('EMAIL_SUBJECT_CONFIRM'), user.email,
- 'confirmation_instructions', user=user,
- confirmation_link=confirmation_link)
-
- confirm_instructions_sent.send(user, app=app._get_current_object())
- return token
-
-
-def generate_confirmation_token(user):
- """Generates a unique confirmation token for the specified user.
-
- :param user: The user to work with
- """
- data = [str(user.id), md5(user.email)]
- return _security.confirm_serializer.dumps(data)
-
-
-def requires_confirmation(user):
- """Returns `True` if the user requires confirmation."""
- return _security.confirmable and user.confirmed_at == None
-
-
-def confirm_email_token_status(token):
- """Returns the expired status, invalid status, and user of a confirmation
- token. For example::
-
- expired, invalid, user = confirm_email_token_status('...')
-
- :param token: The confirmation token
- """
- return get_token_status(token, 'confirm', 'CONFIRM_EMAIL')
-
-
-def confirm_user(user):
- """Confirms the specified user
-
- :param user: The user to confirm
- """
- user.confirmed_at = datetime.utcnow()
- _datastore.put(user)
- user_confirmed.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/core.py b/wqflask/flask_security/core.py
deleted file mode 100644
index 0f3a231f..00000000
--- a/wqflask/flask_security/core.py
+++ /dev/null
@@ -1,382 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.core
- ~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security core module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import current_app
-from flask.ext.login import AnonymousUser as AnonymousUserBase, \
- UserMixin as BaseUserMixin, LoginManager, current_user
-from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \
- identity_loaded
-from itsdangerous import URLSafeTimedSerializer
-from passlib.context import CryptContext
-from werkzeug.datastructures import ImmutableList
-from werkzeug.local import LocalProxy
-
-from .utils import config_value as cv, get_config, md5, url_for_security
-from .views import create_blueprint
-from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \
- ForgotPasswordForm, ChangePasswordForm, ResetPasswordForm, \
- SendConfirmationForm, PasswordlessLoginForm
-
-# Convenient references
-_security = LocalProxy(lambda: current_app.extensions['security'])
-
-
-#: Default Flask-Security configuration
-_default_config = {
- 'BLUEPRINT_NAME': 'security',
- 'URL_PREFIX': None,
- 'SUBDOMAIN': None,
- 'FLASH_MESSAGES': True,
- 'PASSWORD_HASH': 'plaintext',
- 'PASSWORD_SALT': None,
- 'LOGIN_URL': '/login',
- 'LOGOUT_URL': '/logout',
- 'REGISTER_URL': '/register',
- 'RESET_URL': '/reset',
- 'CHANGE_URL': '/change',
- 'CONFIRM_URL': '/confirm',
- 'POST_LOGIN_VIEW': '/',
- 'POST_LOGOUT_VIEW': '/',
- 'CONFIRM_ERROR_VIEW': None,
- 'POST_REGISTER_VIEW': None,
- 'POST_CONFIRM_VIEW': None,
- 'POST_RESET_VIEW': None,
- 'POST_CHANGE_VIEW': None,
- 'UNAUTHORIZED_VIEW': None,
- 'FORGOT_PASSWORD_TEMPLATE': 'security/forgot_password.html',
- 'LOGIN_USER_TEMPLATE': 'security/login_user.html',
- 'REGISTER_USER_TEMPLATE': 'security/register_user.html',
- 'RESET_PASSWORD_TEMPLATE': 'security/reset_password.html',
- 'SEND_CONFIRMATION_TEMPLATE': 'security/send_confirmation.html',
- 'SEND_LOGIN_TEMPLATE': 'security/send_login.html',
- 'CONFIRMABLE': False,
- 'REGISTERABLE': False,
- 'RECOVERABLE': False,
- 'TRACKABLE': False,
- 'PASSWORDLESS': False,
- 'CHANGEABLE': False,
- 'SEND_REGISTER_EMAIL': True,
- 'LOGIN_WITHIN': '1 days',
- 'CONFIRM_EMAIL_WITHIN': '5 days',
- 'RESET_PASSWORD_WITHIN': '5 days',
- 'LOGIN_WITHOUT_CONFIRMATION': False,
- 'EMAIL_SENDER': 'no-reply@localhost',
- 'TOKEN_AUTHENTICATION_KEY': 'auth_token',
- 'TOKEN_AUTHENTICATION_HEADER': 'Authentication-Token',
- 'CONFIRM_SALT': 'confirm-salt',
- 'RESET_SALT': 'reset-salt',
- 'LOGIN_SALT': 'login-salt',
- 'CHANGE_SALT': 'change-salt',
- 'REMEMBER_SALT': 'remember-salt',
- 'DEFAULT_HTTP_AUTH_REALM': 'Login Required',
- 'EMAIL_SUBJECT_REGISTER': 'Welcome',
- 'EMAIL_SUBJECT_CONFIRM': 'Please confirm your email',
- 'EMAIL_SUBJECT_PASSWORDLESS': 'Login instructions',
- 'EMAIL_SUBJECT_PASSWORD_NOTICE': 'Your password has been reset',
- 'EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE': 'Your password has been changed',
- 'EMAIL_SUBJECT_PASSWORD_RESET': 'Password reset instructions'
-}
-
-#: Default Flask-Security messages
-_default_messages = {
- 'UNAUTHORIZED': ('You do not have permission to view this resource.', 'error'),
- 'CONFIRM_REGISTRATION': ('Thank you. Confirmation instructions have been sent to %(email)s.', 'success'),
- 'EMAIL_CONFIRMED': ('Thank you. Your email has been confirmed.', 'success'),
- 'ALREADY_CONFIRMED': ('Your email has already been confirmed.', 'info'),
- 'INVALID_CONFIRMATION_TOKEN': ('Invalid confirmation token.', 'error'),
- 'EMAIL_ALREADY_ASSOCIATED': ('%(email)s is already associated with an account.', 'error'),
- 'PASSWORD_MISMATCH': ('Password does not match', 'error'),
- 'RETYPE_PASSWORD_MISMATCH': ('Passwords do not match', 'error'),
- 'INVALID_REDIRECT': ('Redirections outside the domain are forbidden', 'error'),
- 'PASSWORD_RESET_REQUEST': ('Instructions to reset your password have been sent to %(email)s.', 'info'),
- 'PASSWORD_RESET_EXPIRED': ('You did not reset your password within %(within)s. New instructions have been sent to %(email)s.', 'error'),
- 'INVALID_RESET_PASSWORD_TOKEN': ('Invalid reset password token.', 'error'),
- 'CONFIRMATION_REQUIRED': ('Email requires confirmation.', 'error'),
- 'CONFIRMATION_REQUEST': ('Confirmation instructions have been sent to %(email)s.', 'info'),
- 'CONFIRMATION_EXPIRED': ('You did not confirm your email within %(within)s. New instructions to confirm your email have been sent to %(email)s.', 'error'),
- 'LOGIN_EXPIRED': ('You did not login within %(within)s. New instructions to login have been sent to %(email)s.', 'error'),
- 'LOGIN_EMAIL_SENT': ('Instructions to login have been sent to %(email)s.', 'success'),
- 'INVALID_LOGIN_TOKEN': ('Invalid login token.', 'error'),
- 'DISABLED_ACCOUNT': ('Account is disabled.', 'error'),
- 'EMAIL_NOT_PROVIDED': ('Email not provided', 'error'),
- 'INVALID_EMAIL_ADDRESS': ('Invalid email address', 'error'),
- 'PASSWORD_NOT_PROVIDED': ('Password not provided', 'error'),
- 'USER_DOES_NOT_EXIST': ('Specified user does not exist', 'error'),
- 'INVALID_PASSWORD': ('Invalid password', 'error'),
- 'PASSWORDLESS_LOGIN_SUCCESSFUL': ('You have successfuly logged in.', 'success'),
- 'PASSWORD_RESET': ('You successfully reset your password and you have been logged in automatically.', 'success'),
- 'PASSWORD_CHANGE': ('You successfully changed your password.', 'success'),
- 'LOGIN': ('Please log in to access this page.', 'info'),
- 'REFRESH': ('Please reauthenticate to access this page.', 'info'),
-}
-
-_allowed_password_hash_schemes = [
- 'bcrypt',
- 'des_crypt',
- 'pbkdf2_sha256',
- 'pbkdf2_sha512',
- 'sha256_crypt',
- 'sha512_crypt',
- # And always last one...
- 'plaintext'
-]
-
-_default_forms = {
- 'login_form': LoginForm,
- 'confirm_register_form': ConfirmRegisterForm,
- 'register_form': RegisterForm,
- 'forgot_password_form': ForgotPasswordForm,
- 'reset_password_form': ResetPasswordForm,
- 'change_password_form': ChangePasswordForm,
- 'send_confirmation_form': SendConfirmationForm,
- 'passwordless_login_form': PasswordlessLoginForm,
-}
-
-
-def _user_loader(user_id):
- return _security.datastore.find_user(id=user_id)
-
-
-def _token_loader(token):
- try:
- data = _security.remember_token_serializer.loads(token)
- user = _security.datastore.find_user(id=data[0])
- if user and md5(user.password) == data[1]:
- return user
- except:
- pass
-
- return None
-
-
-def _identity_loader():
- if not isinstance(current_user._get_current_object(), AnonymousUser):
- identity = Identity(current_user.id)
- return identity
-
-
-def _on_identity_loaded(sender, identity):
- if hasattr(current_user, 'id'):
- identity.provides.add(UserNeed(current_user.id))
-
- for role in current_user.roles:
- identity.provides.add(RoleNeed(role.name))
-
- identity.user = current_user
-
-
-def _get_login_manager(app):
- lm = LoginManager()
- lm.anonymous_user = AnonymousUser
- lm.login_view = '%s.login' % cv('BLUEPRINT_NAME', app=app)
- lm.user_loader(_user_loader)
- lm.token_loader(_token_loader)
- lm.login_message, lm.login_message_category = cv('MSG_LOGIN', app=app)
- lm.needs_refresh_message, lm.needs_refresh_message_category = cv('MSG_REFRESH', app=app)
- lm.init_app(app)
- return lm
-
-
-def _get_principal(app):
- p = Principal(app, use_sessions=False)
- p.identity_loader(_identity_loader)
- return p
-
-
-def _get_pwd_context(app):
- pw_hash = cv('PASSWORD_HASH', app=app)
- if pw_hash not in _allowed_password_hash_schemes:
- allowed = ', '.join(_allowed_password_hash_schemes[:-1]) + ' and ' + _allowed_password_hash_schemes[-1]
- raise ValueError("Invalid hash scheme %r. Allowed values are %s" % (pw_hash, allowed))
- return CryptContext(schemes=_allowed_password_hash_schemes, default=pw_hash)
-
-
-def _get_serializer(app, name):
- secret_key = app.config.get('SECRET_KEY')
- salt = app.config.get('SECURITY_%s_SALT' % name.upper())
- return URLSafeTimedSerializer(secret_key=secret_key, salt=salt)
-
-
-def _get_state(app, datastore, **kwargs):
- for key, value in get_config(app).items():
- print "in _get_state [{}]: {}".format(key, value)
- kwargs[key.lower()] = value
-
- kwargs.update(dict(
- app=app,
- datastore=datastore,
- login_manager=_get_login_manager(app),
- principal=_get_principal(app),
- pwd_context=_get_pwd_context(app),
- remember_token_serializer=_get_serializer(app, 'remember'),
- login_serializer=_get_serializer(app, 'login'),
- reset_serializer=_get_serializer(app, 'reset'),
- confirm_serializer=_get_serializer(app, 'confirm'),
- _context_processors={},
- _send_mail_task=None
- ))
-
- for key, value in _default_forms.items():
- if key not in kwargs or not kwargs[key]:
- kwargs[key] = value
-
- return _SecurityState(**kwargs)
-
-
-def _context_processor():
- return dict(url_for_security=url_for_security, security=_security)
-
-
-class RoleMixin(object):
- """Mixin for `Role` model definitions"""
- def __eq__(self, other):
- return (self.name == other or \
- self.name == getattr(other, 'name', None))
-
- def __ne__(self, other):
- return (self.name != other and
- self.name != getattr(other, 'name', None))
-
-
-class UserMixin(BaseUserMixin):
- """Mixin for `User` model definitions"""
-
- def is_active(self):
- """Returns `True` if the user is active."""
- return self.active
-
- def get_auth_token(self):
- """Returns the user's authentication token."""
- data = [str(self.id), md5(self.password)]
- return _security.remember_token_serializer.dumps(data)
-
- def has_role(self, role):
- """Returns `True` if the user identifies with the specified role.
-
- :param role: A role name or `Role` instance"""
- return role in self.roles
-
-
-class AnonymousUser(AnonymousUserBase):
- """AnonymousUser definition"""
-
- def __init__(self):
- super(AnonymousUser, self).__init__()
- self.roles = ImmutableList()
-
- def has_role(self, *args):
- """Returns `False`"""
- return False
-
-
-class _SecurityState(object):
-
- def __init__(self, **kwargs):
- for key, value in kwargs.items():
- setattr(self, key.lower(), value)
-
- def _add_ctx_processor(self, endpoint, fn):
- group = self._context_processors.setdefault(endpoint, [])
- fn not in group and group.append(fn)
-
- def _run_ctx_processor(self, endpoint):
- rv, fns = {}, []
- for g in [None, endpoint]:
- for fn in self._context_processors.setdefault(g, []):
- rv.update(fn())
- return rv
-
- def context_processor(self, fn):
- self._add_ctx_processor(None, fn)
-
- def forgot_password_context_processor(self, fn):
- self._add_ctx_processor('forgot_password', fn)
-
- def login_context_processor(self, fn):
- self._add_ctx_processor('login', fn)
-
- def register_context_processor(self, fn):
- self._add_ctx_processor('register', fn)
-
- def reset_password_context_processor(self, fn):
- self._add_ctx_processor('reset_password', fn)
-
- def change_password_context_processor(self, fn):
- self._add_ctx_processor('change_password', fn)
-
- def send_confirmation_context_processor(self, fn):
- self._add_ctx_processor('send_confirmation', fn)
-
- def send_login_context_processor(self, fn):
- self._add_ctx_processor('send_login', fn)
-
- def mail_context_processor(self, fn):
- self._add_ctx_processor('mail', fn)
-
- def send_mail_task(self, fn):
- self._send_mail_task = fn
-
-
-class Security(object):
- """The :class:`Security` class initializes the Flask-Security extension.
-
- :param app: The application.
- :param datastore: An instance of a user datastore.
- """
- def __init__(self, app=None, datastore=None, **kwargs):
- self.app = app
- self.datastore = datastore
-
- if app is not None and datastore is not None:
- self._state = self.init_app(app, datastore, **kwargs)
-
- def init_app(self, app, datastore=None, register_blueprint=True,
- login_form=None, confirm_register_form=None,
- register_form=None, forgot_password_form=None,
- reset_password_form=None, change_password_form=None,
- send_confirmation_form=None, passwordless_login_form=None):
- """Initializes the Flask-Security extension for the specified
- application and datastore implentation.
-
- :param app: The application.
- :param datastore: An instance of a user datastore.
- :param register_blueprint: to register the Security blueprint or not.
- """
- datastore = datastore or self.datastore
-
- for key, value in _default_config.items():
- app.config.setdefault('SECURITY_' + key, value)
-
- for key, value in _default_messages.items():
- app.config.setdefault('SECURITY_MSG_' + key, value)
-
- identity_loaded.connect_via(app)(_on_identity_loaded)
-
- state = _get_state(app, datastore,
- login_form=login_form,
- confirm_register_form=confirm_register_form,
- register_form=register_form,
- forgot_password_form=forgot_password_form,
- reset_password_form=reset_password_form,
- change_password_form=change_password_form,
- send_confirmation_form=send_confirmation_form,
- passwordless_login_form=passwordless_login_form)
-
- if register_blueprint:
- app.register_blueprint(create_blueprint(state, __name__))
- app.context_processor(_context_processor)
-
- app.extensions['security'] = state
-
- return state
-
- def __getattr__(self, name):
- return getattr(self._state, name, None)
diff --git a/wqflask/flask_security/datastore.py b/wqflask/flask_security/datastore.py
deleted file mode 100644
index 634399d9..00000000
--- a/wqflask/flask_security/datastore.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.datastore
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- This module contains an user datastore classes.
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-class Datastore(object):
- def __init__(self, db):
- self.db = db
-
- def commit(self):
- pass
-
- def put(self, model):
- raise NotImplementedError
-
- def delete(self, model):
- raise NotImplementedError
-
-
-class SQLAlchemyDatastore(Datastore):
- def commit(self):
- self.db.session.commit()
-
- def put(self, model):
- self.db.session.add(model)
- return model
-
- def delete(self, model):
- self.db.session.delete(model)
-
-
-class MongoEngineDatastore(Datastore):
- def put(self, model):
- model.save()
- return model
-
- def delete(self, model):
- model.delete()
-
-
-class PeeweeDatastore(Datastore):
- def put(self, model):
- model.save()
- return model
-
- def delete(self, model):
- model.delete_instance()
-
-
-class UserDatastore(object):
- """Abstracted user datastore.
-
- :param user_model: A user model class definition
- :param role_model: A role model class definition
- """
-
- def __init__(self, user_model, role_model):
- self.user_model = user_model
- self.role_model = role_model
-
- def _prepare_role_modify_args(self, user, role):
- if isinstance(user, basestring):
- user = self.find_user(email=user)
- if isinstance(role, basestring):
- role = self.find_role(role)
- return user, role
-
- def _prepare_create_user_args(self, **kwargs):
- kwargs.setdefault('active', True)
- roles = kwargs.get('roles', [])
- for i, role in enumerate(roles):
- rn = role.name if isinstance(role, self.role_model) else role
- # see if the role exists
- roles[i] = self.find_role(rn)
- kwargs['roles'] = roles
- return kwargs
-
- def find_user(self, *args, **kwargs):
- """Returns a user matching the provided parameters."""
- raise NotImplementedError
-
- def find_role(self, *args, **kwargs):
- """Returns a role matching the provided name."""
- raise NotImplementedError
-
- def add_role_to_user(self, user, role):
- """Adds a role tp a user
-
- :param user: The user to manipulate
- :param role: The role to add to the user
- """
- rv = False
- user, role = self._prepare_role_modify_args(user, role)
- if role not in user.roles:
- rv = True
- user.roles.append(role)
- return rv
-
- def remove_role_from_user(self, user, role):
- """Removes a role from a user
-
- :param user: The user to manipulate
- :param role: The role to remove from the user
- """
- rv = False
- user, role = self._prepare_role_modify_args(user, role)
- if role in user.roles:
- rv = True
- user.roles.remove(role)
- return rv
-
- def toggle_active(self, user):
- """Toggles a user's active status. Always returns True."""
- user.active = not user.active
- return True
-
- def deactivate_user(self, user):
- """Deactivates a specified user. Returns `True` if a change was made.
-
- :param user: The user to deactivate
- """
- if user.active:
- user.active = False
- return True
- return False
-
- def activate_user(self, user):
- """Activates a specified user. Returns `True` if a change was made.
-
- :param user: The user to activate
- """
- if not user.active:
- user.active = True
- return True
- return False
-
- def create_role(self, **kwargs):
- """Creates and returns a new role from the given parameters."""
-
- role = self.role_model(**kwargs)
- return self.put(role)
-
- def find_or_create_role(self, name, **kwargs):
- """Returns a role matching the given name or creates it with any
- additionally provided parameters
- """
- kwargs["name"] = name
- return self.find_role(name) or self.create_role(**kwargs)
-
- def create_user(self, **kwargs):
- """Creates and returns a new user from the given parameters."""
-
- user = self.user_model(**self._prepare_create_user_args(**kwargs))
- print "in abstraced create_user, user is:", user
- return self.put(user)
-
- def delete_user(self, user):
- """Delete the specified user
-
- :param user: The user to delete
- """
- self.delete(user)
-
-
-class SQLAlchemyUserDatastore(SQLAlchemyDatastore, UserDatastore):
- """A SQLAlchemy datastore implementation for Flask-Security that assumes the
- use of the Flask-SQLAlchemy extension.
- """
- def __init__(self, db, user_model, role_model):
- SQLAlchemyDatastore.__init__(self, db)
- UserDatastore.__init__(self, user_model, role_model)
-
- def find_user(self, **kwargs):
- return self.user_model.query.filter_by(**kwargs).first()
-
- def find_role(self, role):
- return self.role_model.query.filter_by(name=role).first()
-
-
-class MongoEngineUserDatastore(MongoEngineDatastore, UserDatastore):
- """A MongoEngine datastore implementation for Flask-Security that assumes
- the use of the Flask-MongoEngine extension.
- """
- def __init__(self, db, user_model, role_model):
- MongoEngineDatastore.__init__(self, db)
- UserDatastore.__init__(self, user_model, role_model)
-
- def find_user(self, **kwargs):
- return self.user_model.objects(**kwargs).first()
-
- def find_role(self, role):
- return self.role_model.objects(name=role).first()
-
-
-class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
- """A PeeweeD datastore implementation for Flask-Security that assumes
- the use of the Flask-Peewee extension.
-
- :param user_model: A user model class definition
- :param role_model: A role model class definition
- :param role_link: A model implementing the many-to-many user-role relation
- """
- def __init__(self, db, user_model, role_model, role_link):
- PeeweeDatastore.__init__(self, db)
- UserDatastore.__init__(self, user_model, role_model)
- self.UserRole = role_link
-
- def find_user(self, **kwargs):
- try:
- return self.user_model.filter(**kwargs).get()
- except self.user_model.DoesNotExist:
- return None
-
- def find_role(self, role):
- try:
- return self.role_model.filter(name=role).get()
- except self.role_model.DoesNotExist:
- return None
-
- def create_user(self, **kwargs):
- """Creates and returns a new user from the given parameters."""
- roles = kwargs.pop('roles', [])
- user = self.user_model(**self._prepare_create_user_args(**kwargs))
- user = self.put(user)
- for role in roles:
- self.add_role_to_user(user, role)
- return user
-
-
- def add_role_to_user(self, user, role):
- """Adds a role tp a user
-
- :param user: The user to manipulate
- :param role: The role to add to the user
- """
- user, role = self._prepare_role_modify_args(user, role)
- if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count():
- return False
- else:
- self.UserRole.create(user=user, role=role)
- return True
-
- def remove_role_from_user(self, user, role):
- """Removes a role from a user
-
- :param user: The user to manipulate
- :param role: The role to remove from the user
- """
- user, role = self._prepare_role_modify_args(user, role)
- if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count():
- self.UserRole.delete().where(self.UserRole.user==user, self.UserRole.role==role)
- return True
- else:
- return False
-
diff --git a/wqflask/flask_security/decorators.py b/wqflask/flask_security/decorators.py
deleted file mode 100644
index 0ea1105c..00000000
--- a/wqflask/flask_security/decorators.py
+++ /dev/null
@@ -1,207 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.decorators
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security decorators module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from functools import wraps
-
-from flask import current_app, Response, request, redirect, _request_ctx_stack
-from flask.ext.login import current_user, login_required
-from flask.ext.principal import RoleNeed, Permission, Identity, identity_changed
-from werkzeug.local import LocalProxy
-
-from . import utils
-
-
-# Convenient references
-_security = LocalProxy(lambda: current_app.extensions['security'])
-
-
-_default_unauthorized_html = """
- <h1>Unauthorized</h1>
- <p>The server could not verify that you are authorized to access the URL
- requested. You either supplied the wrong credentials (e.g. a bad password),
- or your browser doesn't understand how to supply the credentials required.</p>
- """
-
-
-def _get_unauthorized_response(text=None, headers=None):
- text = text or _default_unauthorized_html
- headers = headers or {}
- return Response(text, 401, headers)
-
-
-def _get_unauthorized_view():
- cv = utils.get_url(utils.config_value('UNAUTHORIZED_VIEW'))
- utils.do_flash(*utils.get_message('UNAUTHORIZED'))
- return redirect(cv or request.referrer or '/')
-
-
-def _check_token():
- header_key = _security.token_authentication_header
- args_key = _security.token_authentication_key
- header_token = request.headers.get(header_key, None)
- token = request.args.get(args_key, header_token)
- if request.json:
- token = request.json.get(args_key, token)
- serializer = _security.remember_token_serializer
-
- try:
- data = serializer.loads(token)
- except:
- return False
-
- user = _security.datastore.find_user(id=data[0])
-
- if utils.md5(user.password) == data[1]:
- app = current_app._get_current_object()
- _request_ctx_stack.top.user = user
- identity_changed.send(app, identity=Identity(user.id))
- return True
-
-
-def _check_http_auth():
- auth = request.authorization or dict(username=None, password=None)
- user = _security.datastore.find_user(email=auth.username)
-
- if user and utils.verify_and_update_password(auth.password, user):
- _security.datastore.commit()
- app = current_app._get_current_object()
- _request_ctx_stack.top.user = user
- identity_changed.send(app, identity=Identity(user.id))
- return True
-
- return False
-
-
-def http_auth_required(realm):
- """Decorator that protects endpoints using Basic HTTP authentication.
- The username should be set to the user's email address.
-
- :param realm: optional realm name"""
-
- def decorator(fn):
- @wraps(fn)
- def wrapper(*args, **kwargs):
- if _check_http_auth():
- return fn(*args, **kwargs)
- r = _security.default_http_auth_realm if callable(realm) else realm
- h = {'WWW-Authenticate': 'Basic realm="%s"' % r}
- return _get_unauthorized_response(headers=h)
- return wrapper
-
- if callable(realm):
- return decorator(realm)
- return decorator
-
-
-def auth_token_required(fn):
- """Decorator that protects endpoints using token authentication. The token
- should be added to the request by the client by using a query string
- variable with a name equal to the configuration value of
- `SECURITY_TOKEN_AUTHENTICATION_KEY` or in a request header named that of
- the configuration value of `SECURITY_TOKEN_AUTHENTICATION_HEADER`
- """
-
- @wraps(fn)
- def decorated(*args, **kwargs):
- if _check_token():
- return fn(*args, **kwargs)
- return _get_unauthorized_response()
- return decorated
-
-
-def auth_required(*auth_methods):
- """
- Decorator that protects enpoints through multiple mechanisms
- Example::
-
- @app.route('/dashboard')
- @auth_required('token', 'session')
- def dashboard():
- return 'Dashboard'
-
- :param auth_methods: Specified mechanisms.
- """
- login_mechanisms = {
- 'token': lambda: _check_token(),
- 'basic': lambda: _check_http_auth(),
- 'session': lambda: current_user.is_authenticated()
- }
-
- def wrapper(fn):
- @wraps(fn)
- def decorated_view(*args, **kwargs):
- mechanisms = [login_mechanisms.get(method) for method in auth_methods]
- for mechanism in mechanisms:
- if mechanism and mechanism():
- return fn(*args, **kwargs)
- return _get_unauthorized_response()
- return decorated_view
- return wrapper
-
-
-def roles_required(*roles):
- """Decorator which specifies that a user must have all the specified roles.
- Example::
-
- @app.route('/dashboard')
- @roles_required('admin', 'editor')
- def dashboard():
- return 'Dashboard'
-
- The current user must have both the `admin` role and `editor` role in order
- to view the page.
-
- :param args: The required roles.
- """
- def wrapper(fn):
- @wraps(fn)
- def decorated_view(*args, **kwargs):
- perms = [Permission(RoleNeed(role)) for role in roles]
- for perm in perms:
- if not perm.can():
- return _get_unauthorized_view()
- return fn(*args, **kwargs)
- return decorated_view
- return wrapper
-
-
-def roles_accepted(*roles):
- """Decorator which specifies that a user must have at least one of the
- specified roles. Example::
-
- @app.route('/create_post')
- @roles_accepted('editor', 'author')
- def create_post():
- return 'Create Post'
-
- The current user must have either the `editor` role or `author` role in
- order to view the page.
-
- :param args: The possible roles.
- """
- def wrapper(fn):
- @wraps(fn)
- def decorated_view(*args, **kwargs):
- perm = Permission(*[RoleNeed(role) for role in roles])
- if perm.can():
- return fn(*args, **kwargs)
- return _get_unauthorized_view()
- return decorated_view
- return wrapper
-
-
-def anonymous_user_required(f):
- @wraps(f)
- def wrapper(*args, **kwargs):
- if current_user.is_authenticated():
- return redirect(utils.get_url(_security.post_login_view))
- return f(*args, **kwargs)
- return wrapper
diff --git a/wqflask/flask_security/forms.py b/wqflask/flask_security/forms.py
deleted file mode 100644
index 54677e77..00000000
--- a/wqflask/flask_security/forms.py
+++ /dev/null
@@ -1,286 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.forms
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security forms module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-import inspect
-import urlparse
-
-import flask_wtf as wtf
-
-from flask import request, current_app
-from flask_wtf import Form as BaseForm, TextField, PasswordField, \
- SubmitField, HiddenField, BooleanField, ValidationError, Field
-from flask_login import current_user
-from werkzeug.local import LocalProxy
-
-from .confirmable import requires_confirmation
-from .utils import verify_and_update_password, get_message
-
-# Convenient reference
-_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
-
-_default_field_labels = {
- 'email': 'Email Address',
- 'password': 'Password',
- 'remember_me': 'Remember Me',
- 'login': 'Login',
- 'retype_password': 'Retype Password',
- 'register': 'Register',
- 'send_confirmation': 'Resend Confirmation Instructions',
- 'recover_password': 'Recover Password',
- 'reset_password': 'Reset Password',
- 'retype_password': 'Retype Password',
- 'new_password': 'New Password',
- 'change_password': 'Change Password',
- 'send_login_link': 'Send Login Link'
-}
-
-
-class ValidatorMixin(object):
- def __call__(self, form, field):
- if self.message and self.message.isupper():
- self.message = get_message(self.message)[0]
- return super(ValidatorMixin, self).__call__(form, field)
-
-
-class EqualTo(ValidatorMixin, wtf.EqualTo):
- pass
-
-
-class Required(ValidatorMixin, wtf.Required):
- pass
-
-
-class Email(ValidatorMixin, wtf.Email):
- pass
-
-
-class Length(ValidatorMixin, wtf.Length):
- pass
-
-
-email_required = Required(message='EMAIL_NOT_PROVIDED')
-email_validator = Email(message='INVALID_EMAIL_ADDRESS')
-password_required = Required(message='PASSWORD_NOT_PROVIDED')
-
-
-def get_form_field_label(key):
- return _default_field_labels.get(key, '')
-
-
-def unique_user_email(form, field):
- if _datastore.find_user(email=field.data) is not None:
- msg = get_message('EMAIL_ALREADY_ASSOCIATED', email=field.data)[0]
- raise ValidationError(msg)
-
-
-def valid_user_email(form, field):
- form.user = _datastore.find_user(email=field.data)
- if form.user is None:
- raise ValidationError(get_message('USER_DOES_NOT_EXIST')[0])
-
-
-class Form(BaseForm):
- def __init__(self, *args, **kwargs):
- #print "importing tracer"
- #from wqflask import tracer
- #tracer.turn_on()
- #print "imported tracer"
- print "in Form, args:", args
- print "in Form, kwargs:", kwargs
- if current_app.testing:
- self.TIME_LIMIT = None
- super(Form, self).__init__(*args, **kwargs)
-
-
-class EmailFormMixin():
- email = TextField(get_form_field_label('email'),
- validators=[email_required,
- email_validator])
-
-
-class UserEmailFormMixin():
- user = None
- email = TextField(get_form_field_label('email'),
- validators=[email_required,
- email_validator,
- valid_user_email])
-
-
-class UniqueEmailFormMixin():
- email = TextField(get_form_field_label('email'),
- validators=[email_required,
- email_validator,
- unique_user_email])
-
-
-class PasswordFormMixin():
- password = PasswordField(get_form_field_label('password'),
- validators=[password_required])
-
-
-class NewPasswordFormMixin():
- password = PasswordField(get_form_field_label('password'),
- validators=[password_required,
- Length(min=6, max=128)])
-
-
-class PasswordConfirmFormMixin():
- password_confirm = PasswordField(
- get_form_field_label('retype_password'),
- validators=[EqualTo('password', message='RETYPE_PASSWORD_MISMATCH')])
-
-
-class NextFormMixin():
- next = HiddenField()
-
- def validate_next(self, field):
- url_next = urlparse.urlsplit(field.data)
- url_base = urlparse.urlsplit(request.host_url)
- if url_next.netloc and url_next.netloc != url_base.netloc:
- field.data = ''
- raise ValidationError(get_message('INVALID_REDIRECT')[0])
-
-
-class RegisterFormMixin():
- submit = SubmitField(get_form_field_label('register'))
-
- def to_dict(form):
- def is_field_and_user_attr(member):
- print "in ifaua:", member
- return isinstance(member, Field) and \
- hasattr(_datastore.user_model, member.name)
-
- print("green:", vars(form))
- fields = inspect.getmembers(form, is_field_and_user_attr)
- print("fields:" ,vars(form))
- return dict((key, value.data) for key, value in fields)
-
-
-class SendConfirmationForm(Form, UserEmailFormMixin):
- """The default forgot password form"""
-
- submit = SubmitField(get_form_field_label('send_confirmation'))
-
- def __init__(self, *args, **kwargs):
- super(SendConfirmationForm, self).__init__(*args, **kwargs)
- if request.method == 'GET':
- self.email.data = request.args.get('email', None)
-
- def validate(self):
- if not super(SendConfirmationForm, self).validate():
- return False
- if self.user.confirmed_at is not None:
- self.email.errors.append(get_message('ALREADY_CONFIRMED')[0])
- return False
- return True
-
-
-class ForgotPasswordForm(Form, UserEmailFormMixin):
- """The default forgot password form"""
-
- submit = SubmitField(get_form_field_label('recover_password'))
-
-
-class PasswordlessLoginForm(Form, UserEmailFormMixin):
- """The passwordless login form"""
-
- submit = SubmitField(get_form_field_label('send_login_link'))
-
- def __init__(self, *args, **kwargs):
- super(PasswordlessLoginForm, self).__init__(*args, **kwargs)
-
- def validate(self):
- if not super(PasswordlessLoginForm, self).validate():
- return False
- if not self.user.is_active():
- self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
- return False
- return True
-
-
-class LoginForm(Form, NextFormMixin):
- """The default login form"""
-
- email = TextField(get_form_field_label('email'))
- password = PasswordField(get_form_field_label('password'))
- remember = BooleanField(get_form_field_label('remember_me'))
- submit = SubmitField(get_form_field_label('login'))
-
- def __init__(self, *args, **kwargs):
- super(LoginForm, self).__init__(*args, **kwargs)
-
- def validate(self):
- if not super(LoginForm, self).validate():
- return False
-
- if self.email.data.strip() == '':
- self.email.errors.append(get_message('EMAIL_NOT_PROVIDED')[0])
- return False
-
- if self.password.data.strip() == '':
- self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
- return False
-
- self.user = _datastore.find_user(email=self.email.data)
-
- if self.user is None:
- self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
- return False
- if not verify_and_update_password(self.password.data, self.user):
- self.password.errors.append(get_message('INVALID_PASSWORD')[0])
- return False
- if requires_confirmation(self.user):
- self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
- return False
- if not self.user.is_active():
- self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
- return False
- return True
-
-
-class ConfirmRegisterForm(Form, RegisterFormMixin,
- UniqueEmailFormMixin, NewPasswordFormMixin):
- pass
-
-
-class RegisterForm(ConfirmRegisterForm, PasswordConfirmFormMixin):
- pass
-
-
-class ResetPasswordForm(Form, NewPasswordFormMixin, PasswordConfirmFormMixin):
- """The default reset password form"""
-
- submit = SubmitField(get_form_field_label('reset_password'))
-
-
-class ChangePasswordForm(Form, PasswordFormMixin):
- """The default change password form"""
-
- new_password = PasswordField(get_form_field_label('new_password'),
- validators=[password_required,
- Length(min=6, max=128)])
-
- new_password_confirm = PasswordField(get_form_field_label('retype_password'),
- validators=[EqualTo('new_password', message='RETYPE_PASSWORD_MISMATCH')])
-
- submit = SubmitField(get_form_field_label('change_password'))
-
- def validate(self):
- if not super(ChangePasswordForm, self).validate():
- return False
-
- if self.password.data.strip() == '':
- self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
- return False
- if not verify_and_update_password(self.password.data, current_user):
- self.password.errors.append(get_message('INVALID_PASSWORD')[0])
- return False
- return True
diff --git a/wqflask/flask_security/passwordless.py b/wqflask/flask_security/passwordless.py
deleted file mode 100644
index b0accb2c..00000000
--- a/wqflask/flask_security/passwordless.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.passwordless
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security passwordless module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import request, current_app as app
-from werkzeug.local import LocalProxy
-
-from .signals import login_instructions_sent
-from .utils import send_mail, url_for_security, get_token_status, \
- config_value
-
-
-# Convenient references
-_security = LocalProxy(lambda: app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def send_login_instructions(user):
- """Sends the login instructions email for the specified user.
-
- :param user: The user to send the instructions to
- :param token: The login token
- """
- token = generate_login_token(user)
- url = url_for_security('token_login', token=token)
- login_link = request.url_root[:-1] + url
-
- send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email,
- 'login_instructions', user=user, login_link=login_link)
-
- login_instructions_sent.send(dict(user=user, login_token=token),
- app=app._get_current_object())
-
-
-def generate_login_token(user):
- """Generates a unique login token for the specified user.
-
- :param user: The user the token belongs to
- """
- return _security.login_serializer.dumps([str(user.id)])
-
-
-def login_token_status(token):
- """Returns the expired status, invalid status, and user of a login token.
- For example::
-
- expired, invalid, user = login_token_status('...')
-
- :param token: The login token
- """
- return get_token_status(token, 'login', 'LOGIN')
diff --git a/wqflask/flask_security/recoverable.py b/wqflask/flask_security/recoverable.py
deleted file mode 100644
index 6aafc111..00000000
--- a/wqflask/flask_security/recoverable.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.recoverable
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security recoverable module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import current_app as app, request
-from werkzeug.local import LocalProxy
-
-from .signals import password_reset, reset_password_instructions_sent
-from .utils import send_mail, md5, encrypt_password, url_for_security, \
- get_token_status, config_value
-
-
-# Convenient references
-_security = LocalProxy(lambda: app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def send_reset_password_instructions(user):
- """Sends the reset password instructions email for the specified user.
-
- :param user: The user to send the instructions to
- """
- token = generate_reset_password_token(user)
- url = url_for_security('reset_password', token=token)
- reset_link = request.url_root[:-1] + url
-
- send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'), user.email,
- 'reset_instructions',
- user=user, reset_link=reset_link)
-
- reset_password_instructions_sent.send(dict(user=user, token=token),
- app=app._get_current_object())
-
-
-def send_password_reset_notice(user):
- """Sends the password reset notice email for the specified user.
-
- :param user: The user to send the notice to
- """
- send_mail(config_value('EMAIL_SUBJECT_PASSWORD_NOTICE'), user.email,
- 'reset_notice', user=user)
-
-
-def generate_reset_password_token(user):
- """Generates a unique reset password token for the specified user.
-
- :param user: The user to work with
- """
- data = [str(user.id), md5(user.password)]
- return _security.reset_serializer.dumps(data)
-
-
-def reset_password_token_status(token):
- """Returns the expired status, invalid status, and user of a password reset
- token. For example::
-
- expired, invalid, user = reset_password_token_status('...')
-
- :param token: The password reset token
- """
- return get_token_status(token, 'reset', 'RESET_PASSWORD')
-
-def update_password(user, password):
- """Update the specified user's password
-
- :param user: The user to update_password
- :param password: The unencrypted new password
- """
- user.password = encrypt_password(password)
- _datastore.put(user)
- send_password_reset_notice(user)
- password_reset.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/registerable.py b/wqflask/flask_security/registerable.py
deleted file mode 100644
index 4606c7c6..00000000
--- a/wqflask/flask_security/registerable.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.registerable
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security registerable module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import current_app as app
-from werkzeug.local import LocalProxy
-
-from .confirmable import generate_confirmation_link
-from .signals import user_registered
-from .utils import do_flash, get_message, send_mail, encrypt_password, \
- config_value
-
-# Convenient references
-_security = LocalProxy(lambda: app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def register_user(**kwargs):
- print "in register_user kwargs:", kwargs
- confirmation_link, token = None, None
- kwargs['password'] = encrypt_password(kwargs['password'])
- user = _datastore.create_user(**kwargs)
- _datastore.commit()
-
- if _security.confirmable:
- confirmation_link, token = generate_confirmation_link(user)
- do_flash(*get_message('CONFIRM_REGISTRATION', email=user.email))
-
- user_registered.send(dict(user=user, confirm_token=token),
- app=app._get_current_object())
-
- if config_value('SEND_REGISTER_EMAIL'):
- send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email, 'welcome',
- user=user, confirmation_link=confirmation_link)
-
- return user
diff --git a/wqflask/flask_security/script.py b/wqflask/flask_security/script.py
deleted file mode 100644
index 9c9a2469..00000000
--- a/wqflask/flask_security/script.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.script
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security script module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-try:
- import simplejson as json
-except ImportError:
- import json
-
-import re
-
-from flask import current_app
-from flask.ext.script import Command, Option
-from werkzeug.local import LocalProxy
-
-from .utils import encrypt_password
-
-
-_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
-
-
-def pprint(obj):
- print json.dumps(obj, sort_keys=True, indent=4)
-
-
-def commit(fn):
- def wrapper(*args, **kwargs):
- fn(*args, **kwargs)
- _datastore.commit()
- return wrapper
-
-
-class CreateUserCommand(Command):
- """Create a user"""
-
- option_list = (
- Option('-e', '--email', dest='email', default=None),
- Option('-p', '--password', dest='password', default=None),
- Option('-a', '--active', dest='active', default=''),
- )
-
- @commit
- def run(self, **kwargs):
- # sanitize active input
- ai = re.sub(r'\s', '', str(kwargs['active']))
- kwargs['active'] = ai.lower() in ['', 'y', 'yes', '1', 'active']
-
- from flask_security.forms import ConfirmRegisterForm
- from werkzeug.datastructures import MultiDict
-
- form = ConfirmRegisterForm(MultiDict(kwargs), csrf_enabled=False)
-
- if form.validate():
- kwargs['password'] = encrypt_password(kwargs['password'])
- _datastore.create_user(**kwargs)
- print 'User created successfully.'
- kwargs['password'] = '****'
- pprint(kwargs)
- else:
- print 'Error creating user'
- pprint(form.errors)
-
-
-class CreateRoleCommand(Command):
- """Create a role"""
-
- option_list = (
- Option('-n', '--name', dest='name', default=None),
- Option('-d', '--desc', dest='description', default=None),
- )
-
- @commit
- def run(self, **kwargs):
- _datastore.create_role(**kwargs)
- print 'Role "%(name)s" created successfully.' % kwargs
-
-
-class _RoleCommand(Command):
- option_list = (
- Option('-u', '--user', dest='user_identifier'),
- Option('-r', '--role', dest='role_name'),
- )
-
-
-class AddRoleCommand(_RoleCommand):
- """Add a role to a user"""
-
- @commit
- def run(self, user_identifier, role_name):
- _datastore.add_role_to_user(user_identifier, role_name)
- print "Role '%s' added to user '%s' successfully" % (role_name, user_identifier)
-
-
-class RemoveRoleCommand(_RoleCommand):
- """Add a role to a user"""
-
- @commit
- def run(self, user_identifier, role_name):
- _datastore.remove_role_from_user(user_identifier, role_name)
- print "Role '%s' removed from user '%s' successfully" % (role_name, user_identifier)
-
-
-class _ToggleActiveCommand(Command):
- option_list = (
- Option('-u', '--user', dest='user_identifier'),
- )
-
-
-class DeactivateUserCommand(_ToggleActiveCommand):
- """Deactive a user"""
-
- @commit
- def run(self, user_identifier):
- _datastore.deactivate_user(user_identifier)
- print "User '%s' has been deactivated" % user_identifier
-
-
-class ActivateUserCommand(_ToggleActiveCommand):
- """Deactive a user"""
-
- @commit
- def run(self, user_identifier):
- _datastore.activate_user(user_identifier)
- print "User '%s' has been activated" % user_identifier
diff --git a/wqflask/flask_security/signals.py b/wqflask/flask_security/signals.py
deleted file mode 100644
index e1c29548..00000000
--- a/wqflask/flask_security/signals.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.signals
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security signals module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-import blinker
-
-
-signals = blinker.Namespace()
-
-user_registered = signals.signal("user-registered")
-
-user_confirmed = signals.signal("user-confirmed")
-
-confirm_instructions_sent = signals.signal("confirm-instructions-sent")
-
-login_instructions_sent = signals.signal("login-instructions-sent")
-
-password_reset = signals.signal("password-reset")
-
-password_changed = signals.signal("password-changed")
-
-reset_password_instructions_sent = signals.signal("password-reset-instructions-sent")
diff --git a/wqflask/flask_security/templates/.DS_Store b/wqflask/flask_security/templates/.DS_Store
deleted file mode 100644
index b72f1d98..00000000
--- a/wqflask/flask_security/templates/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/wqflask/flask_security/templates/security/.DS_Store b/wqflask/flask_security/templates/security/.DS_Store
deleted file mode 100644
index 5008ddfc..00000000
--- a/wqflask/flask_security/templates/security/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/wqflask/flask_security/templates/security/_macros.html b/wqflask/flask_security/templates/security/_macros.html
deleted file mode 100644
index 8575f3db..00000000
--- a/wqflask/flask_security/templates/security/_macros.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% macro render_field_with_errors(field) %}
- <p>
- {{ field.label }} {{ field(**kwargs)|safe }}
- {% if field.errors %}
- <ul>
- {% for error in field.errors %}
- <li>{{ error }}</li>
- {% endfor %}
- </ul>
- {% endif %}
- </p>
-{% endmacro %}
-
-{% macro render_field(field) %}
- <p>{{ field(**kwargs)|safe }}</p>
-{% endmacro %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/_menu.html b/wqflask/flask_security/templates/security/_menu.html
deleted file mode 100644
index 5291f809..00000000
--- a/wqflask/flask_security/templates/security/_menu.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% if security.registerable or security.recoverable or security.confirmabled %}
-<h2>Menu</h2>
-<ul>
- <li><a href="{{ url_for_security('login') }}">Login</a></li>
- {% if security.registerable %}
- <li><a href="{{ url_for_security('register') }}">Register</a><br/></li>
- {% endif %}
- {% if security.recoverable %}
- <li><a href="{{ url_for_security('forgot_password') }}">Forgot password</a><br/></li>
- {% endif %}
- {% if security.confirmable %}
- <li><a href="{{ url_for_security('send_confirmation') }}">Confirm account</a></li>
- {% endif %}
-</ul>
-{% endif %}
diff --git a/wqflask/flask_security/templates/security/_messages.html b/wqflask/flask_security/templates/security/_messages.html
deleted file mode 100644
index 179d0636..00000000
--- a/wqflask/flask_security/templates/security/_messages.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{%- with messages = get_flashed_messages(with_categories=true) -%}
- {% if messages %}
- <ul class="flashes">
- {% for category, message in messages %}
- <li class="{{ category }}">{{ message }}</li>
- {% endfor %}
- </ul>
- {% endif %}
-{%- endwith %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/change_password.html b/wqflask/flask_security/templates/security/change_password.html
deleted file mode 100644
index 8ee3eb73..00000000
--- a/wqflask/flask_security/templates/security/change_password.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Change password</h1>
-<form action="{{ url_for_security('change_password') }}" method="POST" name="change_password_form">
- {{ change_password_form.hidden_tag() }}
- {{ render_field_with_errors(change_password_form.password) }}
- {{ render_field_with_errors(change_password_form.new_password) }}
- {{ render_field_with_errors(change_password_form.new_password_confirm) }}
- {{ render_field(change_password_form.submit) }}
-</form>
-
diff --git a/wqflask/flask_security/templates/security/email/change_notice.html b/wqflask/flask_security/templates/security/email/change_notice.html
deleted file mode 100644
index d1224cf5..00000000
--- a/wqflask/flask_security/templates/security/email/change_notice.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<p>Your password has been changed.</p>
-{% if security.recoverable %}
-<p>If you did not change your password, <a href="{{ url_for_security('forgot_password', _external=True) }}">click here to reset it</a>.</p>
-{% endif %}
diff --git a/wqflask/flask_security/templates/security/email/change_notice.txt b/wqflask/flask_security/templates/security/email/change_notice.txt
deleted file mode 100644
index e74bd80d..00000000
--- a/wqflask/flask_security/templates/security/email/change_notice.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Your password has been changed
-{% if security.recoverable %}
-If you did not change your password, click the link below to reset it.
-{{ url_for_security('forgot_password', _external=True) }}
-{% endif %}
diff --git a/wqflask/flask_security/templates/security/email/confirmation_instructions.html b/wqflask/flask_security/templates/security/email/confirmation_instructions.html
deleted file mode 100644
index 5082a9a8..00000000
--- a/wqflask/flask_security/templates/security/email/confirmation_instructions.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<p>Please confirm your email through the link below:</p>
-
-<p><a href="{{ confirmation_link }}">Confirm my account</a></p> \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/confirmation_instructions.txt b/wqflask/flask_security/templates/security/email/confirmation_instructions.txt
deleted file mode 100644
index fb435b55..00000000
--- a/wqflask/flask_security/templates/security/email/confirmation_instructions.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Please confirm your email through the link below:
-
-{{ confirmation_link }} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/login_instructions.html b/wqflask/flask_security/templates/security/email/login_instructions.html
deleted file mode 100644
index 45a7cb57..00000000
--- a/wqflask/flask_security/templates/security/email/login_instructions.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>Welcome {{ user.email }}!</p>
-
-<p>You can log into your through the link below:</p>
-
-<p><a href="{{ login_link }}">Login now</a></p> \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/login_instructions.txt b/wqflask/flask_security/templates/security/email/login_instructions.txt
deleted file mode 100644
index 1364ed65..00000000
--- a/wqflask/flask_security/templates/security/email/login_instructions.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Welcome {{ user.email }}!
-
-You can log into your through the link below:
-
-{{ login_link }} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_instructions.html b/wqflask/flask_security/templates/security/email/reset_instructions.html
deleted file mode 100644
index fd0b48d8..00000000
--- a/wqflask/flask_security/templates/security/email/reset_instructions.html
+++ /dev/null
@@ -1 +0,0 @@
-<p><a href="{{ reset_link }}">Click here to reset your password</a></p> \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_instructions.txt b/wqflask/flask_security/templates/security/email/reset_instructions.txt
deleted file mode 100644
index 91ac288e..00000000
--- a/wqflask/flask_security/templates/security/email/reset_instructions.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Click the link below to reset your password:
-
-{{ reset_link }} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_notice.html b/wqflask/flask_security/templates/security/email/reset_notice.html
deleted file mode 100644
index 536e2961..00000000
--- a/wqflask/flask_security/templates/security/email/reset_notice.html
+++ /dev/null
@@ -1 +0,0 @@
-<p>Your password has been reset</p> \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_notice.txt b/wqflask/flask_security/templates/security/email/reset_notice.txt
deleted file mode 100644
index a3fa0b4b..00000000
--- a/wqflask/flask_security/templates/security/email/reset_notice.txt
+++ /dev/null
@@ -1 +0,0 @@
-Your password has been reset \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/welcome.html b/wqflask/flask_security/templates/security/email/welcome.html
deleted file mode 100644
index 55eaed61..00000000
--- a/wqflask/flask_security/templates/security/email/welcome.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<p>Welcome {{ user.email }}!</p>
-
-{% if security.confirmable %}
-<p>You can confirm your email through the link below:</p>
-
-<p><a href="{{ confirmation_link }}">Confirm my account</a></p>
-{% endif %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/welcome.txt b/wqflask/flask_security/templates/security/email/welcome.txt
deleted file mode 100644
index fb6ee5b5..00000000
--- a/wqflask/flask_security/templates/security/email/welcome.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Welcome {{ user.email }}!
-
-{% if security.confirmable %}
-You can confirm your email through the link below:
-
-{{ confirmation_link }}
-{% endif %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/forgot_password.html b/wqflask/flask_security/templates/security/forgot_password.html
deleted file mode 100644
index 90fcaf66..00000000
--- a/wqflask/flask_security/templates/security/forgot_password.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Send password reset instructions</h1>
-<form action="{{ url_for_security('forgot_password') }}" method="POST" name="forgot_password_form">
- {{ forgot_password_form.hidden_tag() }}
- {{ render_field_with_errors(forgot_password_form.email) }}
- {{ render_field(forgot_password_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/login_user.html b/wqflask/flask_security/templates/security/login_user.html
deleted file mode 100644
index d781ce08..00000000
--- a/wqflask/flask_security/templates/security/login_user.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Login</h1>
-<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
- {{ login_user_form.hidden_tag() }}
- {{ render_field_with_errors(login_user_form.email) }}
- {{ render_field_with_errors(login_user_form.password) }}
- {{ render_field_with_errors(login_user_form.remember) }}
- {{ render_field(login_user_form.next) }}
- {{ render_field(login_user_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/register_user.html b/wqflask/flask_security/templates/security/register_user.html
deleted file mode 100644
index 87cf9b1d..00000000
--- a/wqflask/flask_security/templates/security/register_user.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Register</h1>
-<form action="{{ url_for_security('register') }}" method="POST" name="register_user_form">
- {{ register_user_form.hidden_tag() }}
- {{ render_field_with_errors(register_user_form.email) }}
- {{ render_field_with_errors(register_user_form.password) }}
- {% if register_user_form.password_confirm %}
- {{ render_field_with_errors(register_user_form.password_confirm) }}
- {% endif %}
- {{ render_field(register_user_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/reset_password.html b/wqflask/flask_security/templates/security/reset_password.html
deleted file mode 100644
index e6fc3f58..00000000
--- a/wqflask/flask_security/templates/security/reset_password.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Reset password</h1>
-<form action="{{ url_for_security('reset_password', token=reset_password_token) }}" method="POST" name="reset_password_form">
- {{ reset_password_form.hidden_tag() }}
- {{ render_field_with_errors(reset_password_form.password) }}
- {{ render_field_with_errors(reset_password_form.password_confirm) }}
- {{ render_field(reset_password_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/send_confirmation.html b/wqflask/flask_security/templates/security/send_confirmation.html
deleted file mode 100644
index 3e828407..00000000
--- a/wqflask/flask_security/templates/security/send_confirmation.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Resend confirmation instructions</h1>
-<form action="{{ url_for_security('send_confirmation') }}" method="POST" name="send_confirmation_form">
- {{ send_confirmation_form.hidden_tag() }}
- {{ render_field_with_errors(send_confirmation_form.email) }}
- {{ render_field(send_confirmation_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/send_login.html b/wqflask/flask_security/templates/security/send_login.html
deleted file mode 100644
index 15611c57..00000000
--- a/wqflask/flask_security/templates/security/send_login.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
-{% include "security/_messages.html" %}
-<h1>Login</h1>
-<form action="{{ url_for_security('login') }}" method="POST" name="send_login_form">
- {{ send_login_form.hidden_tag() }}
- {{ render_field_with_errors(send_login_form.email) }}
- {{ render_field(send_login_form.submit) }}
-</form>
-{% include "security/_menu.html" %} \ No newline at end of file
diff --git a/wqflask/flask_security/utils.py b/wqflask/flask_security/utils.py
deleted file mode 100644
index 7397ab4f..00000000
--- a/wqflask/flask_security/utils.py
+++ /dev/null
@@ -1,379 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.utils
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security utils module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-import base64
-import blinker
-import functools
-import hashlib
-import hmac
-from contextlib import contextmanager
-from datetime import datetime, timedelta
-
-from flask import url_for, flash, current_app, request, session, render_template
-from flask.ext.login import login_user as _login_user, \
- logout_user as _logout_user
-from flask.ext.mail import Message
-from flask.ext.principal import Identity, AnonymousIdentity, identity_changed
-from itsdangerous import BadSignature, SignatureExpired
-from werkzeug.local import LocalProxy
-
-from .signals import user_registered, user_confirmed, \
- confirm_instructions_sent, login_instructions_sent, \
- password_reset, password_changed, reset_password_instructions_sent
-
-# Convenient references
-_security = LocalProxy(lambda: current_app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-_pwd_context = LocalProxy(lambda: _security.pwd_context)
-
-
-def login_user(user, remember=True):
- """Performs the login and sends the appropriate signal."""
-
- if not _login_user(user, remember):
- return False
-
- if _security.trackable:
- old_current_login, new_current_login = user.current_login_at, datetime.utcnow()
- remote_addr = request.remote_addr or 'untrackable'
- old_current_ip, new_current_ip = user.current_login_ip, remote_addr
-
- user.last_login_at = old_current_login or new_current_login
- user.current_login_at = new_current_login
- user.last_login_ip = old_current_ip or new_current_ip
- user.current_login_ip = new_current_ip
- user.login_count = user.login_count + 1 if user.login_count else 1
-
- _datastore.put(user)
-
- identity_changed.send(current_app._get_current_object(),
- identity=Identity(user.id))
- return True
-
-
-def logout_user():
- for key in ('identity.name', 'identity.auth_type'):
- session.pop(key, None)
- identity_changed.send(current_app._get_current_object(),
- identity=AnonymousIdentity())
- _logout_user()
-
-
-def get_hmac(password):
- if _security.password_hash == 'plaintext':
- return password
-
- if _security.password_salt is None:
- raise RuntimeError('The configuration value `SECURITY_PASSWORD_SALT` '
- 'must not be None when the value of `SECURITY_PASSWORD_HASH` is '
- 'set to "%s"' % _security.password_hash)
-
- h = hmac.new(_security.password_salt, password.encode('utf-8'), hashlib.sha512)
- return base64.b64encode(h.digest())
-
-
-def verify_password(password, password_hash):
- return _pwd_context.verify(get_hmac(password), password_hash)
-
-
-def verify_and_update_password(password, user):
- verified, new_password = _pwd_context.verify_and_update(get_hmac(password), user.password)
- if verified and new_password:
- user.password = new_password
- _datastore.put(user)
- return verified
-
-
-def encrypt_password(password):
- return _pwd_context.encrypt(get_hmac(password))
-
-
-def md5(data):
- return hashlib.md5(data).hexdigest()
-
-
-def do_flash(message, category=None):
- """Flash a message depending on if the `FLASH_MESSAGES` configuration
- value is set.
-
- :param message: The flash message
- :param category: The flash message category
- """
- if config_value('FLASH_MESSAGES'):
- flash(message, category)
-
-
-def get_url(endpoint_or_url):
- """Returns a URL if a valid endpoint is found. Otherwise, returns the
- provided value.
-
- :param endpoint_or_url: The endpoint name or URL to default to
- """
- try:
- return url_for(endpoint_or_url)
- except:
- return endpoint_or_url
-
-
-def get_security_endpoint_name(endpoint):
- return '%s.%s' % (_security.blueprint_name, endpoint)
-
-
-def url_for_security(endpoint, **values):
- """Return a URL for the security blueprint
-
- :param endpoint: the endpoint of the URL (name of the function)
- :param values: the variable arguments of the URL rule
- :param _external: if set to `True`, an absolute URL is generated. Server
- address can be changed via `SERVER_NAME` configuration variable which
- defaults to `localhost`.
- :param _anchor: if provided this is added as anchor to the URL.
- :param _method: if provided this explicitly specifies an HTTP method.
- """
- endpoint = get_security_endpoint_name(endpoint)
- return url_for(endpoint, **values)
-
-
-def get_post_login_redirect():
- """Returns the URL to redirect to after a user logs in successfully."""
- return (get_url(request.args.get('next')) or
- get_url(request.form.get('next')) or
- find_redirect('SECURITY_POST_LOGIN_VIEW'))
-
-
-def find_redirect(key):
- """Returns the URL to redirect to after a user logs in successfully.
-
- :param key: The session or application configuration key to search for
- """
- rv = (get_url(session.pop(key.lower(), None)) or
- get_url(current_app.config[key.upper()] or None) or '/')
- return rv
-
-
-def get_config(app):
- """Conveniently get the security configuration for the specified
- application without the annoying 'SECURITY_' prefix.
-
- :param app: The application to inspect
- """
- items = app.config.items()
- prefix = 'SECURITY_'
-
- def strip_prefix(tup):
- return (tup[0].replace('SECURITY_', ''), tup[1])
-
- return dict([strip_prefix(i) for i in items if i[0].startswith(prefix)])
-
-
-def get_message(key, **kwargs):
- rv = config_value('MSG_' + key)
- return rv[0] % kwargs, rv[1]
-
-
-def config_value(key, app=None, default=None):
- """Get a Flask-Security configuration value.
-
- :param key: The configuration key without the prefix `SECURITY_`
- :param app: An optional specific application to inspect. Defaults to Flask's
- `current_app`
- :param default: An optional default value if the value is not set
- """
- app = app or current_app
- return get_config(app).get(key.upper(), default)
-
-
-def get_max_age(key, app=None):
- now = datetime.utcnow()
- expires = now + get_within_delta(key + '_WITHIN', app)
- td = (expires - now)
- return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6
-
-
-def get_within_delta(key, app=None):
- """Get a timedelta object from the application configuration following
- the internal convention of::
-
- <Amount of Units> <Type of Units>
-
- Examples of valid config values::
-
- 5 days
- 10 minutes
-
- :param key: The config value key without the 'SECURITY_' prefix
- :param app: Optional application to inspect. Defaults to Flask's
- `current_app`
- """
- txt = config_value(key, app=app)
- values = txt.split()
- return timedelta(**{values[1]: int(values[0])})
-
-
-def send_mail(subject, recipient, template, **context):
- """Send an email via the Flask-Mail extension.
-
- :param subject: Email subject
- :param recipient: Email recipient
- :param template: The name of the email template
- :param context: The context to render the template with
- """
-
- context.setdefault('security', _security)
- context.update(_security._run_ctx_processor('mail'))
-
- msg = Message(subject,
- sender=_security.email_sender,
- recipients=[recipient])
-
- ctx = ('security/email', template)
- msg.body = render_template('%s/%s.txt' % ctx, **context)
- msg.html = render_template('%s/%s.html' % ctx, **context)
-
- if _security._send_mail_task:
- _security._send_mail_task(msg)
- return
-
- mail = current_app.extensions.get('mail')
- mail.send(msg)
-
-
-def get_token_status(token, serializer, max_age=None):
- serializer = getattr(_security, serializer + '_serializer')
- max_age = get_max_age(max_age)
- user, data = None, None
- expired, invalid = False, False
-
- try:
- data = serializer.loads(token, max_age=max_age)
- except SignatureExpired:
- d, data = serializer.loads_unsafe(token)
- expired = True
- except BadSignature:
- invalid = True
-
- if data:
- user = _datastore.find_user(id=data[0])
-
- expired = expired and (user is not None)
- return expired, invalid, user
-
-
-@contextmanager
-def capture_passwordless_login_requests():
- login_requests = []
-
- def _on(data, app):
- login_requests.append(data)
-
- login_instructions_sent.connect(_on)
-
- try:
- yield login_requests
- finally:
- login_instructions_sent.disconnect(_on)
-
-
-@contextmanager
-def capture_registrations():
- """Testing utility for capturing registrations.
-
- :param confirmation_sent_at: An optional datetime object to set the
- user's `confirmation_sent_at` to
- """
- registrations = []
-
- def _on(data, app):
- registrations.append(data)
-
- user_registered.connect(_on)
-
- try:
- yield registrations
- finally:
- user_registered.disconnect(_on)
-
-
-@contextmanager
-def capture_reset_password_requests(reset_password_sent_at=None):
- """Testing utility for capturing password reset requests.
-
- :param reset_password_sent_at: An optional datetime object to set the
- user's `reset_password_sent_at` to
- """
- reset_requests = []
-
- def _on(request, app):
- reset_requests.append(request)
-
- reset_password_instructions_sent.connect(_on)
-
- try:
- yield reset_requests
- finally:
- reset_password_instructions_sent.disconnect(_on)
-
-
-class CaptureSignals(object):
- """Testing utility for capturing blinker signals.
-
- Context manager which mocks out selected signals and registers which are `sent` on and what
- arguments were sent. Instantiate with a list of blinker `NamedSignals` to patch. Each signal
- has it's `send` mocked out.
- """
- def __init__(self, signals):
- """Patch all given signals and make them available as attributes.
-
- :param signals: list of signals
- """
- self._records = {}
- self._receivers = {}
- for signal in signals:
- self._records[signal] = []
- self._receivers[signal] = functools.partial(self._record, signal)
-
- def __getitem__(self, signal):
- """All captured signals are available via `ctxt[signal]`.
- """
- if isinstance(signal, blinker.base.NamedSignal):
- return self._records[signal]
- else:
- super(CaptureSignals, self).__setitem__(signal)
-
- def _record(self, signal, *args, **kwargs):
- self._records[signal].append((args, kwargs))
-
- def __enter__(self):
- for signal, receiver in self._receivers.iteritems():
- signal.connect(receiver)
- return self
-
- def __exit__(self, type, value, traceback):
- for signal, receiver in self._receivers.iteritems():
- signal.disconnect(receiver)
-
- def signals_sent(self):
- """Return a set of the signals sent.
- :rtype: list of blinker `NamedSignals`.
- """
- return set([signal for signal, _ in self._records.iteritems() if self._records[signal]])
-
-
-def capture_signals():
- """Factory method that creates a `CaptureSignals` with all the flask_security signals."""
- return CaptureSignals([user_registered, user_confirmed,
- confirm_instructions_sent, login_instructions_sent,
- password_reset, password_changed,
- reset_password_instructions_sent])
-
-
diff --git a/wqflask/flask_security/views.py b/wqflask/flask_security/views.py
deleted file mode 100644
index 1b8488d8..00000000
--- a/wqflask/flask_security/views.py
+++ /dev/null
@@ -1,359 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flask.ext.security.views
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- Flask-Security views module
-
- :copyright: (c) 2012 by Matt Wright.
- :license: MIT, see LICENSE for more details.
-"""
-
-from flask import current_app, redirect, request, render_template, jsonify, \
- after_this_request, Blueprint
-from flask_login import current_user
-from werkzeug.datastructures import MultiDict
-from werkzeug.local import LocalProxy
-
-from .confirmable import send_confirmation_instructions, \
- confirm_user, confirm_email_token_status
-from .decorators import login_required, anonymous_user_required
-from .passwordless import send_login_instructions, \
- login_token_status
-from .recoverable import reset_password_token_status, \
- send_reset_password_instructions, update_password
-from .changeable import change_user_password
-from .registerable import register_user
-from .utils import get_url, get_post_login_redirect, do_flash, \
- get_message, login_user, logout_user, url_for_security as url_for, \
- config_value
-
-
-# Convenient references
-_security = LocalProxy(lambda: current_app.extensions['security'])
-
-_datastore = LocalProxy(lambda: _security.datastore)
-
-
-def _render_json(form, include_auth_token=False):
- has_errors = len(form.errors) > 0
-
- if has_errors:
- code = 400
- response = dict(errors=form.errors)
- else:
- code = 200
- response = dict(user=dict(id=str(form.user.id)))
- if include_auth_token:
- token = form.user.get_auth_token()
- response['user']['authentication_token'] = token
-
- return jsonify(dict(meta=dict(code=code), response=response))
-
-
-def _commit(response=None):
- _datastore.commit()
- return response
-
-
-def _ctx(endpoint):
- return _security._run_ctx_processor(endpoint)
-
-
-@anonymous_user_required
-def login():
- """View function for login view"""
-
- form_class = _security.login_form
-
- if request.json:
- form = form_class(MultiDict(request.json))
- else:
- form = form_class()
-
- if form.validate_on_submit():
- login_user(form.user, remember=form.remember.data)
- after_this_request(_commit)
-
- if not request.json:
- return redirect(get_post_login_redirect())
-
- form.next.data = get_url(request.args.get('next')) \
- or get_url(request.form.get('next')) or ''
-
- if request.json:
- return _render_json(form, True)
-
- return render_template(config_value('LOGIN_USER_TEMPLATE'),
- login_user_form=form,
- **_ctx('login'))
-
-
-@login_required
-def logout():
- """View function which handles a logout request."""
-
- logout_user()
-
- return redirect(request.args.get('next', None) or
- get_url(_security.post_logout_view))
-
-
-def register():
- """View function which handles a registration request."""
-
- if _security.confirmable or request.json:
- form_class = _security.confirm_register_form
- else:
- form_class = _security.register_form
-
- if request.json:
- form_data = MultiDict(request.json)
- else:
- form_data = request.form
-
- form = form_class(form_data)
-
- if form.validate_on_submit():
- user = register_user(**form.to_dict())
- form.user = user
-
- if not _security.confirmable or _security.login_without_confirmation:
- after_this_request(_commit)
- login_user(user)
-
- if not request.json:
- post_register_url = get_url(_security.post_register_view)
- post_login_url = get_url(_security.post_login_view)
- return redirect(post_register_url or post_login_url)
-
- if request.json:
- return _render_json(form)
-
- return render_template(config_value('REGISTER_USER_TEMPLATE'),
- register_user_form=form,
- **_ctx('register'))
-
-
-def send_login():
- """View function that sends login instructions for passwordless login"""
-
- form_class = _security.passwordless_login_form
-
- if request.json:
- form = form_class(MultiDict(request.json))
- else:
- form = form_class()
-
- if form.validate_on_submit():
- send_login_instructions(form.user)
- if request.json is None:
- do_flash(*get_message('LOGIN_EMAIL_SENT', email=form.user.email))
-
- if request.json:
- return _render_json(form)
-
- return render_template(config_value('SEND_LOGIN_TEMPLATE'),
- send_login_form=form,
- **_ctx('send_login'))
-
-
-@anonymous_user_required
-def token_login(token):
- """View function that handles passwordless login via a token"""
-
- expired, invalid, user = login_token_status(token)
-
- if invalid:
- do_flash(*get_message('INVALID_LOGIN_TOKEN'))
- if expired:
- send_login_instructions(user)
- do_flash(*get_message('LOGIN_EXPIRED', email=user.email,
- within=_security.login_within))
- if invalid or expired:
- return redirect(url_for('login'))
-
- login_user(user, True)
- after_this_request(_commit)
- do_flash(*get_message('PASSWORDLESS_LOGIN_SUCCESSFUL'))
-
- return redirect(get_post_login_redirect())
-
-
-def send_confirmation():
- """View function which sends confirmation instructions."""
-
- form_class = _security.send_confirmation_form
-
- if request.json:
- form = form_class(MultiDict(request.json))
- else:
- form = form_class()
-
- if form.validate_on_submit():
- send_confirmation_instructions(form.user)
- if request.json is None:
- do_flash(*get_message('CONFIRMATION_REQUEST', email=form.user.email))
-
- if request.json:
- return _render_json(form)
-
- return render_template(config_value('SEND_CONFIRMATION_TEMPLATE'),
- send_confirmation_form=form,
- **_ctx('send_confirmation'))
-
-
-@anonymous_user_required
-def confirm_email(token):
- """View function which handles a email confirmation request."""
-
- expired, invalid, user = confirm_email_token_status(token)
-
- if not user or invalid:
- invalid = True
- do_flash(*get_message('INVALID_CONFIRMATION_TOKEN'))
- if expired:
- send_confirmation_instructions(user)
- do_flash(*get_message('CONFIRMATION_EXPIRED', email=user.email,
- within=_security.confirm_email_within))
- if invalid or expired:
- return redirect(get_url(_security.confirm_error_view) or
- url_for('send_confirmation'))
-
- confirm_user(user)
- login_user(user, True)
- after_this_request(_commit)
- do_flash(*get_message('EMAIL_CONFIRMED'))
-
- return redirect(get_url(_security.post_confirm_view) or
- get_url(_security.post_login_view))
-
-
-def forgot_password():
- """View function that handles a forgotten password request."""
-
- form_class = _security.forgot_password_form
-
- if request.json:
- form = form_class(MultiDict(request.json))
- else:
- form = form_class()
-
- if form.validate_on_submit():
- send_reset_password_instructions(form.user)
- if request.json is None:
- do_flash(*get_message('PASSWORD_RESET_REQUEST', email=form.user.email))
-
- if request.json:
- return _render_json(form)
-
- return render_template(config_value('FORGOT_PASSWORD_TEMPLATE'),
- forgot_password_form=form,
- **_ctx('forgot_password'))
-
-
-@anonymous_user_required
-def reset_password(token):
- """View function that handles a reset password request."""
-
- expired, invalid, user = reset_password_token_status(token)
-
- if invalid:
- do_flash(*get_message('INVALID_RESET_PASSWORD_TOKEN'))
- if expired:
- do_flash(*get_message('PASSWORD_RESET_EXPIRED', email=user.email,
- within=_security.reset_password_within))
- if invalid or expired:
- return redirect(url_for('forgot_password'))
-
- form = _security.reset_password_form()
-
- if form.validate_on_submit():
- after_this_request(_commit)
- update_password(user, form.password.data)
- do_flash(*get_message('PASSWORD_RESET'))
- login_user(user, True)
- return redirect(get_url(_security.post_reset_view) or
- get_url(_security.post_login_view))
-
- return render_template(config_value('RESET_PASSWORD_TEMPLATE'),
- reset_password_form=form,
- reset_password_token=token,
- **_ctx('reset_password'))
-
-
-@login_required
-def change_password():
- """View function which handles a change password request."""
-
- form_class = _security.change_password_form
-
- if request.json:
- form = form_class(MultiDict(request.json))
- else:
- form = form_class()
-
- if form.validate_on_submit():
- after_this_request(_commit)
- change_user_password(current_user, form.new_password.data)
- if request.json is None:
- do_flash(*get_message('PASSWORD_CHANGE'))
- return redirect(get_url(_security.post_change_view) or
- get_url(_security.post_login_view))
-
- if request.json:
- return _render_json(form)
-
- return render_template('security/change_password.html',
- change_password_form=form,
- **_ctx('change_password'))
-
-
-def create_blueprint(state, import_name):
- """Creates the security extension blueprint"""
-
- bp = Blueprint(state.blueprint_name, import_name,
- url_prefix=state.url_prefix,
- subdomain=state.subdomain,
- template_folder='templates')
-
- bp.route(state.logout_url, endpoint='logout')(logout)
-
- if state.passwordless:
- bp.route(state.login_url,
- methods=['GET', 'POST'],
- endpoint='login')(send_login)
- bp.route(state.login_url + '/<token>',
- endpoint='token_login')(token_login)
- else:
- bp.route(state.login_url,
- methods=['GET', 'POST'],
- endpoint='login')(login)
-
- if state.registerable:
- bp.route(state.register_url,
- methods=['GET', 'POST'],
- endpoint='register')(register)
-
- if state.recoverable:
- bp.route(state.reset_url,
- methods=['GET', 'POST'],
- endpoint='forgot_password')(forgot_password)
- bp.route(state.reset_url + '/<token>',
- methods=['GET', 'POST'],
- endpoint='reset_password')(reset_password)
-
- if state.changeable:
- bp.route(state.change_url,
- methods=['GET', 'POST'],
- endpoint='change_password')(change_password)
-
- if state.confirmable:
- bp.route(state.confirm_url,
- methods=['GET', 'POST'],
- endpoint='send_confirmation')(send_confirmation)
- bp.route(state.confirm_url + '/<token>',
- methods=['GET', 'POST'],
- endpoint='confirm_email')(confirm_email)
-
- return bp
diff --git a/wqflask/run_gunicorn.py b/wqflask/run_gunicorn.py
index ebe3add5..adffdca3 100644
--- a/wqflask/run_gunicorn.py
+++ b/wqflask/run_gunicorn.py
@@ -7,12 +7,12 @@
# from flask import Flask
# application = Flask(__name__)
-print "Starting up Gunicorn process"
+print "===> Starting up Gunicorn process"
from wqflask import app
+from utility.startup_config import app_config
-app.config['SESSION_TYPE'] = 'filesystem'
-app.config['SECRET_KEY'] = 'super secret key'
+app_config()
@app.route("/gunicorn")
def hello():
diff --git a/wqflask/runserver.py b/wqflask/runserver.py
index a0c76e51..5f41d04d 100644
--- a/wqflask/runserver.py
+++ b/wqflask/runserver.py
@@ -21,22 +21,9 @@ GREEN = '\033[92m'
BOLD = '\033[1m'
ENDC = '\033[0m'
-import os
-app.config['SECRET_KEY'] = os.urandom(24)
+from utility.startup_config import app_config
-from utility.tools import WEBSERVER_MODE,get_setting_int,get_setting,get_setting_bool
-
-port = get_setting_int("SERVER_PORT")
-
-print("GN2 API server URL is ["+BLUE+get_setting("GN_SERVER_URL")+ENDC+"]")
-
-if get_setting_bool("USE_GN_SERVER"):
- import requests
- page = requests.get(get_setting("GN_SERVER_URL"))
- if page.status_code != 200:
- raise Exception("API server not found!")
-
-print("GN2 is running. Visit %s[http://localhost:%s/%s](%s)" % (BLUE,str(port),ENDC,get_setting("WEBSERVER_URL")))
+app_config()
werkzeug_logger = logging.getLogger('werkzeug')
diff --git a/wqflask/utility/elasticsearch_tools.py b/wqflask/utility/elasticsearch_tools.py
index 2d3d5add..075a8f65 100644
--- a/wqflask/utility/elasticsearch_tools.py
+++ b/wqflask/utility/elasticsearch_tools.py
@@ -6,6 +6,11 @@ logger = getLogger(__name__)
from utility.tools import ELASTICSEARCH_HOST, ELASTICSEARCH_PORT
+def test_elasticsearch_connection():
+ es = Elasticsearch(['http://'+ELASTICSEARCH_HOST+":"+str(ELASTICSEARCH_PORT)+'/'], verify_certs=True)
+ if not es.ping():
+ logger.warning("Elasticsearch is DOWN")
+
def get_elasticsearch_connection():
logger.info("get_elasticsearch_connection")
es = None
diff --git a/wqflask/utility/startup_config.py b/wqflask/utility/startup_config.py
new file mode 100644
index 00000000..5a62cc50
--- /dev/null
+++ b/wqflask/utility/startup_config.py
@@ -0,0 +1,39 @@
+
+from wqflask import app
+from utility.tools import WEBSERVER_MODE, show_settings, get_setting_int, get_setting, get_setting_bool
+
+import utility.logger
+logger = utility.logger.getLogger(__name__ )
+
+BLUE = '\033[94m'
+GREEN = '\033[92m'
+BOLD = '\033[1m'
+ENDC = '\033[0m'
+
+def app_config():
+ app.config['SESSION_TYPE'] = 'filesystem'
+ if not app.config.get('SECRET_KEY'):
+ import os
+ app.config['SECRET_KEY'] = str(os.urandom(24))
+
+ mode = WEBSERVER_MODE
+ if mode == "DEV" or mode == "DEBUG":
+ app.config['TEMPLATES_AUTO_RELOAD'] = True
+ # if mode == "DEBUG":
+ # app.config['EXPLAIN_TEMPLATE_LOADING'] = True <--- use overriding app param instead
+ print("==========================================")
+ show_settings()
+
+ port = get_setting_int("SERVER_PORT")
+
+ if get_setting_bool("USE_GN_SERVER"):
+ print("GN2 API server URL is ["+BLUE+get_setting("GN_SERVER_URL")+ENDC+"]")
+ import requests
+ page = requests.get(get_setting("GN_SERVER_URL"))
+ if page.status_code != 200:
+ raise Exception("API server not found!")
+
+ import utility.elasticsearch_tools as es
+ es.test_elasticsearch_connection()
+
+ print("GN2 is running. Visit %s[http://localhost:%s/%s](%s)" % (BLUE,str(port),ENDC,get_setting("WEBSERVER_URL")))
diff --git a/wqflask/utility/tools.py b/wqflask/utility/tools.py
index 8c9fed96..59bb49d8 100644
--- a/wqflask/utility/tools.py
+++ b/wqflask/utility/tools.py
@@ -54,7 +54,7 @@ def get_setting(command_id,guess=None):
# print("Looking for "+command_id+"\n")
command = value(os.environ.get(command_id))
if command is None or command == "":
- command = OVERRIDES.get(command_id)
+ command = OVERRIDES.get(command_id) # currently not in use
if command is None:
# ---- Check whether setting exists in app
command = value(app.config.get(command_id))
@@ -220,7 +220,7 @@ def show_settings():
logger.info(OVERRIDES)
logger.info(BLUE+"Mr. Mojo Risin 2"+ENDC)
- print "runserver.py: ****** Webserver configuration ******"
+ print "runserver.py: ****** Webserver configuration - k,v pairs from app.config ******"
keylist = app.config.keys()
keylist.sort()
for k in keylist:
@@ -254,18 +254,23 @@ JS_GN_PATH = get_setting('JS_GN_PATH')
GITHUB_CLIENT_ID = get_setting('GITHUB_CLIENT_ID')
GITHUB_CLIENT_SECRET = get_setting('GITHUB_CLIENT_SECRET')
GITHUB_AUTH_URL = None
-if GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET:
- GITHUB_AUTH_URL = "https://github.com/login/oauth/authorize?client_id="+GITHUB_CLIENT_ID+"&client_secret="+GITHUB_CLIENT_SECRET
-GITHUB_API_URL = get_setting('GITHUB_API_URL')
+if GITHUB_CLIENT_ID != 'UNKNOWN' and GITHUB_CLIENT_SECRET:
+ GITHUB_AUTH_URL = "https://github.com/login/oauth/authorize?client_id=" + \
+ GITHUB_CLIENT_ID+"&client_secret="+GITHUB_CLIENT_SECRET
+ GITHUB_API_URL = get_setting('GITHUB_API_URL')
+
ORCID_CLIENT_ID = get_setting('ORCID_CLIENT_ID')
ORCID_CLIENT_SECRET = get_setting('ORCID_CLIENT_SECRET')
ORCID_AUTH_URL = None
-if ORCID_CLIENT_ID and ORCID_CLIENT_SECRET:
- ORCID_AUTH_URL = "https://sandbox.orcid.org/oauth/authorize?response_type=code&scope=/authenticate&show_login=true&client_id="+ORCID_CLIENT_ID+"&client_secret="+ORCID_CLIENT_SECRET
-ORCID_TOKEN_URL = get_setting('ORCID_TOKEN_URL')
+if ORCID_CLIENT_ID != 'UNKNOWN' and ORCID_CLIENT_SECRET:
+ ORCID_AUTH_URL = "https://sandbox.orcid.org/oauth/authorize?response_type=code&scope=/authenticate&show_login=true&client_id=" + \
+ ORCID_CLIENT_ID+"&client_secret="+ORCID_CLIENT_SECRET
+ ORCID_TOKEN_URL = get_setting('ORCID_TOKEN_URL')
ELASTICSEARCH_HOST = get_setting('ELASTICSEARCH_HOST')
ELASTICSEARCH_PORT = get_setting('ELASTICSEARCH_PORT')
+import utility.elasticsearch_tools as es
+es.test_elasticsearch_connection()
SMTP_CONNECT = get_setting('SMTP_CONNECT')
SMTP_USERNAME = get_setting('SMTP_USERNAME')
@@ -285,18 +290,5 @@ assert_dir(JS_TWITTER_POST_FETCHER_PATH)
from six import string_types
-if os.environ.get('WQFLASK_OVERRIDES'):
- jsonfn = get_setting('WQFLASK_OVERRIDES')
- logger.info("WQFLASK_OVERRIDES: %s" % jsonfn)
- with open(jsonfn) as data_file:
- overrides = json.load(data_file)
- for k in overrides:
- cmd = overrides[k]
- if isinstance(cmd, string_types):
- OVERRIDES[k] = eval(cmd)
- else:
- OVERRIDES[k] = cmd
- logger.debug(OVERRIDES)
-
# assert_file(PHEWAS_FILES+"/auwerx/PheWAS_pval_EMMA_norm.RData")
assert_file(JS_TWITTER_POST_FETCHER_PATH+"/js/twitterFetcher_min.js")
diff --git a/wqflask/utility/type_checking.py b/wqflask/utility/type_checking.py
new file mode 100644
index 00000000..220e5f62
--- /dev/null
+++ b/wqflask/utility/type_checking.py
@@ -0,0 +1,42 @@
+# Type checking functions
+
+def is_float(value):
+ try:
+ float(value)
+ return True
+ except:
+ return False
+
+def is_int(value):
+ try:
+ int(value)
+ return True
+ except:
+ return False
+
+def is_str(value):
+ if value is None:
+ return False
+ try:
+ str(value)
+ return True
+ except:
+ return False
+
+def get_float(vars,name,default=None):
+ if name in vars:
+ if is_float(vars[name]):
+ return float(vars[name])
+ return None
+
+def get_int(vars,name,default=None):
+ if name in vars:
+ if is_int(vars[name]):
+ return float(vars[name])
+ return default
+
+def get_string(vars,name,default=None):
+ if name in vars:
+ if not vars[name] is None:
+ return str(vars[name])
+ return default
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index 2188ce17..bc8e9900 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -13,8 +13,8 @@ logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
app.config.from_object('cfg.default_settings') # Get the defaults from cfg.default_settings
-app.config.from_envvar('WQFLASK_SETTINGS') # See http://flask.pocoo.org/docs/config/#configuring-from-files
-# Note we also use WQFLASK_OVERRIDES
+app.config.from_envvar('GN2_SETTINGS') # See http://flask.pocoo.org/docs/config/#configuring-from-files
+# Note no longer use the badly named WQFLASK_OVERRIDES (nyi)
app.jinja_env.globals.update(
undefined = jinja2.StrictUndefined,
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index 2f6c3a96..629977ac 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -36,6 +36,10 @@ from utility.formatting import numify
from base import trait
from base.data_set import create_dataset
+import logging
+from utility.logger import getLogger
+logger = getLogger(__name__)
+
def get_collection():
if g.user_session.logged_in:
return UserCollection()
@@ -93,7 +97,7 @@ class AnonCollection(object):
self.traits = list(process_traits(params['traits']))
#len_before = len(Redis.smembers(self.key))
existing_collections = Redis.get(self.key)
- print("existing_collections:", existing_collections)
+ logger.debug("existing_collections:", existing_collections)
if existing_collections != None and existing_collections != "None":
collections_list = json.loads(existing_collections)
collection_position = 0 #ZS: Position of collection in collection_list, if it exists
@@ -158,8 +162,8 @@ class UserCollection(object):
"""User is logged in"""
def add_traits(self, params, collection_name):
- print("---> params are:", params.keys())
- print(" type(params):", type(params))
+ logger.debug("---> params are:", params.keys())
+ logger.debug(" type(params):", type(params))
if collection_name=="Default":
uc = g.user_session.user_ob.get_collection_by_name("Default")
# Doesn't exist so we'll create it
@@ -187,7 +191,7 @@ class UserCollection(object):
db_session.commit()
- print("added to existing, now set is:" + str(uc.members))
+ logger.debug("added to existing, now set is:" + str(uc.members))
report_change(len_before, len_now)
# Probably have to change that
@@ -210,12 +214,12 @@ def process_traits(unprocessed_traits):
def report_change(len_before, len_now):
new_length = len_now - len_before
if new_length:
- print("We've added {} to your collection.".format(
+ logger.debug("We've added {} to your collection.".format(
numify(new_length, 'new trait', 'new traits')))
flash("We've added {} to your collection.".format(
numify(new_length, 'new trait', 'new traits')))
else:
- print("No new traits were added.")
+ logger.debug("No new traits were added.")
@app.route("/collections/add")
@@ -224,7 +228,7 @@ def collections_add():
if g.user_session.logged_in:
user_collections = g.user_session.user_ob.user_collections
- print("user_collections are:", user_collections)
+ logger.debug("user_collections are:", user_collections)
return render_template("collections/add.html",
traits = traits,
collections = user_collections,
@@ -246,11 +250,11 @@ def collections_new():
if "sign_in" in params:
return redirect(url_for('login'))
if "create_new" in params:
- print("in create_new")
+ logger.debug("in create_new")
collection_name = params['new_collection']
return create_new(collection_name)
elif "add_to_existing" in params:
- print("in add to existing")
+ logger.debug("in add to existing")
collection_name = params['existing_collection'].split(":")[1]
if g.user_session.logged_in:
return UserCollection().add_traits(params, collection_name)
@@ -270,7 +274,7 @@ def create_new(collection_name):
if g.user_session.logged_in:
uc = model.UserCollection()
uc.name = collection_name
- print("user_session:", g.user_session.__dict__)
+ logger.debug("user_session:", g.user_session.__dict__)
uc.user = g.user_session.user_id
uc.members = json.dumps(list(traits))
db_session.add(uc)
@@ -286,17 +290,17 @@ def create_new(collection_name):
@app.route("/collections/list")
def list_collections():
params = request.args
- print("PARAMS:", params)
+ logger.debug("PARAMS:", params)
if g.user_session.logged_in:
user_collections = list(g.user_session.user_ob.user_collections)
- print("user_collections are:", user_collections)
+ logger.debug("user_collections are:", user_collections)
return render_template("collections/list.html",
params = params,
collections = user_collections,
)
else:
anon_collections = user_manager.AnonUser().get_collections()
- print("anon_collections are:", anon_collections)
+ logger.debug("anon_collections are:", anon_collections)
return render_template("collections/list.html",
params = params,
collections = anon_collections)
@@ -305,17 +309,17 @@ def list_collections():
@app.route("/collections/remove", methods=('POST',))
def remove_traits():
params = request.form
- print("params are:", params)
+ logger.debug("params are:", params)
if "uc_id" in params:
uc_id = params['uc_id']
uc = model.UserCollection.query.get(uc_id)
traits_to_remove = params.getlist('traits[]')
traits_to_remove = process_traits(traits_to_remove)
- print("\n\n after processing, traits_to_remove:", traits_to_remove)
+ logger.debug("\n\n after processing, traits_to_remove:", traits_to_remove)
all_traits = uc.members_as_set()
members_now = all_traits - traits_to_remove
- print(" members_now:", members_now)
+ logger.debug(" members_now:", members_now)
uc.members = json.dumps(list(members_now))
uc.changed_timestamp = datetime.datetime.utcnow()
db_session.commit()
@@ -332,7 +336,7 @@ def remove_traits():
@app.route("/collections/delete", methods=('POST',))
def delete_collection():
params = request.form
- print("params:", params)
+ logger.debug("params:", params)
if g.user_session.logged_in:
uc_id = params['uc_id']
if len(uc_id.split(":")) > 1:
@@ -349,8 +353,11 @@ def delete_collection():
db_session.delete(uc)
db_session.commit()
else:
- collection_name = params['collection_name']
- user_manager.AnonUser().delete_collection(collection_name)
+ if "collection_name" in params:
+ collection_name = params['collection_name']
+ else:
+ for this_collection in params['uc_id'].split(":"):
+ user_manager.AnonUser().delete_collection(this_collection)
flash("We've deleted the collection: {}.".format(collection_name), "alert-info")
@@ -360,7 +367,7 @@ def delete_collection():
@app.route("/collections/view")
def view_collection():
params = request.args
- print("PARAMS in view collection:", params)
+ logger.debug("PARAMS in view collection:", params)
if "uc_id" in params:
uc_id = params['uc_id']
@@ -376,7 +383,7 @@ def view_collection():
#this_collection = user_collections[params['collection_id']]
traits = this_collection['members']
- print("in view_collection traits are:", traits)
+ logger.debug("in view_collection traits are:", traits)
trait_obs = []
json_version = []
@@ -402,7 +409,7 @@ def view_collection():
collection_info = dict(trait_obs=trait_obs,
collection_name=this_collection['name'])
if "json" in params:
- print("json_version:", json_version)
+ logger.debug("json_version:", json_version)
return json.dumps(json_version)
else:
return render_template("collections/view.html",
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 3d1c0d17..2c6c3a14 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -32,6 +32,7 @@ import pp
import math
import collections
import resource
+import json
import scipy
@@ -51,6 +52,8 @@ import utility.webqtlUtil #this is for parallel computing only.
from wqflask.correlation import correlation_functions
from utility.benchmark import Bench
import utility.webqtlUtil
+from utility.type_checking import is_float, is_int, is_str, get_float, get_int, get_string
+from wqflask import user_manager
from MySQLdb import escape_string as escape
@@ -75,47 +78,6 @@ def print_mem(stage=""):
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
#print("{}: {}".format(stage, mem/1024))
-def is_float(value):
- try:
- float(value)
- return True
- except:
- return False
-
-def is_int(value):
- try:
- int(value)
- return True
- except:
- return False
-
-def is_str(value):
- if value is None:
- return False
- try:
- str(value)
- return True
- except:
- return False
-
-def get_float(vars,name,default=None):
- if name in vars:
- if is_float(vars[name]):
- return float(vars[name])
- return None
-
-def get_int(vars,name,default=None):
- if name in vars:
- if is_int(vars[name]):
- return float(vars[name])
- return default
-
-def get_string(vars,name,default=None):
- if name in vars:
- if not vars[name] is None:
- return str(vars[name])
- return default
-
class AuthException(Exception):
pass
@@ -248,7 +210,7 @@ class CorrelationResults(object):
else:
self.this_trait_vals.append("None")
num_overlap = len(self.this_trait_vals)
-
+ logger.debug("DOING PARALLEL")
self.do_parallel_correlation(db_filename, num_overlap)
else:
for trait, values in self.target_dataset.trait_data.iteritems():
@@ -335,6 +297,7 @@ class CorrelationResults(object):
#print("self.correlation_results: ", pf(self.correlation_results))
+ self.json_results = generate_corr_json(self.correlation_results, self.this_trait, self.dataset, self.target_dataset)
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
@@ -1195,6 +1158,17 @@ class CorrelationResults(object):
import math
import reaper
+ def cmpOrder2(A,B):
+ try:
+ if A[-1] < B[-1]:
+ return -1
+ elif A[-1] == B[-1]:
+ return 0
+ else:
+ return 1
+ except:
+ return 0
+
def calCorrelation(dbdata,userdata,N):
X = []
Y = []
@@ -1420,3 +1394,61 @@ class CorrelationResults(object):
# for one_result in results:
# for one_traitinfo in one_result:
# allcorrelations.append( one_traitinfo )
+
+def generate_corr_json(corr_results, this_trait, dataset, target_dataset):
+ results_list = []
+ for i, trait in enumerate(corr_results):
+ results_dict = {}
+ results_dict['checkbox'] = "<INPUT TYPE='checkbox' NAME='searchResult' class='checkbox trait_checkbox' style='padding-right: 0px;' VALUE='" + user_manager.data_hmac('{}:{}'.format(trait.name, trait.dataset.name)) + "'>"
+ results_dict['index'] = i + 1
+ results_dict['trait_id'] = "<a href='/show_trait?trait_id="+str(trait.name)+"&dataset="+str(dataset.name)+"'>"+str(trait.name)+"</a>"
+ if target_dataset.type == "ProbeSet":
+ results_dict['symbol'] = trait.symbol
+ results_dict['description'] = trait.description_display
+ results_dict['location'] = trait.location_repr
+ results_dict['mean'] = float(trait.mean)
+ if trait.LRS_score_repr != "N/A":
+ results_dict['lrs_score'] = "%.1f" % float(trait.LRS_score_repr)
+ else:
+ results_dict['lrs_score'] = "N/A"
+ results_dict['lrs_location'] = trait.LRS_location_repr
+ if trait.additive != "":
+ results_dict['additive'] = "%0.3f" % float(trait.additive)
+ else:
+ results_dict['additive'] = "N/A"
+ results_dict['sample_r'] = "<a target='_blank' href='corr_scatter_plot?dataset_1=" + str(dataset.name) + "&dataset_2=" + str(trait.dataset.name) + "&trait_1=" + str(this_trait.name) + "&trait_2=" + str(trait.name) + "'>" + "%0.3f" % float(trait.sample_r) + "</a>"
+ results_dict['num_overlap'] = trait.num_overlap
+ results_dict['sample_p'] = "%0.3e" % float(trait.sample_p)
+ if trait.lit_corr == "" or trait.lit_corr == 0:
+ results_dict['lit_corr'] = "--"
+ else:
+ results_dict['lit_corr'] = "%0.3f" % float(trait.lit_corr)
+ if trait.tissue_corr == "" or trait.tissue_corr == 0:
+ results_dict['tissue_corr'] = "--"
+ else:
+ results_dict['tissue_corr'] = "%0.3f" % float(trait.tissue_corr)
+ elif target_dataset.type == "Publish":
+ results_dict['description'] = trait.description_display
+ results_dict['authors'] = trait.authors
+ if trait.pubmed_id:
+ results_dict['pubmed'] = "<a href='" + trait.pubmed_link + "'> " + trait.pubmed_text + "</a>"
+ else:
+ results_dict['pubmed'] = "N/A"
+ results_dict['lrs_score'] = trait.LRS_score_repr
+ results_dict['lrs_location'] = trait.LRS_location_repr
+ if trait.additive != "":
+ results_dict['additive'] = "%0.3f" % float(trait.additive)
+ else:
+ results_dict['additive'] = "N/A"
+ results_dict['sample_r'] = "<a target='_blank' href='corr_scatter_plot?dataset_1=" + str(dataset.name) + "&dataset_2=" + str(trait.dataset.name) + "&trait_1=" + str(this_trait.name) + "&trait_2=" + str(trait.name) + "'>" + "%0.3f" % trait.sample_r + "</a>"
+ results_dict['num_overlap'] = trait.num_overlap
+ results_dict['sample_p'] = "%0.3e" % float(trait.sample_p)
+ else:
+ results_dict['lrs_location'] = trait.LRS_location_repr
+ results_dict['sample_r'] = "<a target='_blank' href='corr_scatter_plot?dataset_1=" + str(dataset.name) + "&dataset_2=" + str(trait.dataset.name) + "&trait_1=" + str(this_trait.name) + "&trait_2=" + str(trait.name) + "'>" + "%0.3f" % float(trait.sample_r) + "</a>"
+ results_dict['num_overlap'] = trait.num_overlap
+ results_dict['sample_p'] = "%0.3e" % float(trait.sample_p)
+
+ results_list.append(results_dict)
+
+ return json.dumps(results_list)
diff --git a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py
index b34beb7b..077386a3 100644
--- a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py
+++ b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py
@@ -173,9 +173,12 @@ class CorrelationMatrix(object):
for sample in self.all_sample_list:
groups.append(1)
- pca = self.calculate_pca(range(len(self.traits)), corr_eigen_value, corr_eigen_vectors)
-
- self.loadings_array = self.process_loadings()
+ try:
+ self.pca_works = "True"
+ pca = self.calculate_pca(range(len(self.traits)), corr_eigen_value, corr_eigen_vectors)
+ self.loadings_array = self.process_loadings()
+ except:
+ self.pca_works = "False"
self.js_data = dict(traits = [trait.name for trait in self.traits],
groups = groups,
diff --git a/wqflask/wqflask/gsearch.py b/wqflask/wqflask/gsearch.py
index e33e04e1..fe1e17d2 100644
--- a/wqflask/wqflask/gsearch.py
+++ b/wqflask/wqflask/gsearch.py
@@ -5,6 +5,7 @@ from base.data_set import create_dataset
from base.trait import GeneralTrait
from db import webqtlDatabaseFunction
+from utility.type_checking import is_float, is_int, is_str, get_float, get_int, get_string
from utility.benchmark import Bench
from utility.logger import getLogger
@@ -13,8 +14,13 @@ logger = getLogger(__name__)
class GSearch(object):
def __init__(self, kw):
+ assert('type' in kw)
+ assert('terms' in kw)
+
self.type = kw['type']
self.terms = kw['terms']
+ assert(is_str(self.type))
+
if self.type == "gene":
sql = """
SELECT
diff --git a/wqflask/wqflask/marker_regression/gemma_mapping.py b/wqflask/wqflask/marker_regression/gemma_mapping.py
index 68920130..7563eb2c 100644
--- a/wqflask/wqflask/marker_regression/gemma_mapping.py
+++ b/wqflask/wqflask/marker_regression/gemma_mapping.py
@@ -3,7 +3,7 @@ import os, math, string, random, json
from base import webqtlConfig
from base.trait import GeneralTrait
from base.data_set import create_dataset
-from utility.tools import flat_files, GEMMA_COMMAND, GEMMA_WRAPPER_COMMAND, TEMPDIR, assert_bin, assert_file
+from utility.tools import flat_files, GEMMA_COMMAND, GEMMA_WRAPPER_COMMAND, TEMPDIR
import utility.logger
logger = utility.logger.getLogger(__name__ )
@@ -11,7 +11,6 @@ logger = utility.logger.getLogger(__name__ )
def run_gemma(this_dataset, samples, vals, covariates, method, use_loco):
"""Generates p-values for each marker using GEMMA"""
- assert_bin(GEMMA_COMMAND);
if this_dataset.group.genofile != None:
genofile_name = this_dataset.group.genofile[:-5]
else:
@@ -193,7 +192,7 @@ def parse_gemma_output(genofile_name):
# if marker['chr'] != previous_chr:
# previous_chr = marker['chr']
marker['Mb'] = float(line.split("\t")[2]) / 1000000
- marker['p_value'] = float(line.split("\t")[10])
+ marker['p_value'] = float(line.split("\t")[11])
if math.isnan(marker['p_value']) or (marker['p_value'] <= 0):
marker['lod_score'] = 0
#marker['lrs_value'] = 0
@@ -203,20 +202,15 @@ def parse_gemma_output(genofile_name):
marker_obs.append(marker)
included_markers.append(line.split("\t")[1])
- p_values.append(float(line.split("\t")[10]))
+ p_values.append(float(line.split("\t")[11]))
return marker_obs
def parse_loco_output(this_dataset, gwa_output_filename):
output_filelist = []
- jsonfn = "{}/gn2/".format(TEMPDIR) + gwa_output_filename + ".json"
- assert_file(jsonfn)
- try:
- with open(jsonfn) as data_file:
- data = json.load(data_file)
- except:
- logger.error("Can not parse "+jsonfn)
+ with open("{}/gn2/".format(TEMPDIR) + gwa_output_filename + ".json") as data_file:
+ data = json.load(data_file)
files = data['files']
for file in files:
@@ -241,7 +235,7 @@ def parse_loco_output(this_dataset, gwa_output_filename):
else:
marker['chr'] = line.split("\t")[0]
marker['Mb'] = float(line.split("\t")[2]) / 1000000
- marker['p_value'] = float(line.split("\t")[10])
+ marker['p_value'] = float(line.split("\t")[11])
if math.isnan(marker['p_value']) or (marker['p_value'] <= 0):
marker['lod_score'] = 0
#marker['lrs_value'] = 0
@@ -251,6 +245,6 @@ def parse_loco_output(this_dataset, gwa_output_filename):
marker_obs.append(marker)
included_markers.append(line.split("\t")[1])
- p_values.append(float(line.split("\t")[10]))
+ p_values.append(float(line.split("\t")[11]))
- return marker_obs
+ return marker_obs \ No newline at end of file
diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py
index c189fb96..3ec61e55 100644
--- a/wqflask/wqflask/marker_regression/marker_regression.py
+++ b/wqflask/wqflask/marker_regression/marker_regression.py
@@ -228,6 +228,7 @@ class MarkerRegression(object):
results, self.json_data, self.perm_output, self.suggestive, self.significant, self.bootstrap_results = qtlreaper_mapping.gen_reaper_results(self.this_trait,
self.dataset,
self.samples,
+ self.vals,
self.json_data,
self.num_perm,
self.bootCheck,
diff --git a/wqflask/wqflask/marker_regression/marker_regression_gn1.py b/wqflask/wqflask/marker_regression/marker_regression_gn1.py
index 211cf187..66884b0c 100644
--- a/wqflask/wqflask/marker_regression/marker_regression_gn1.py
+++ b/wqflask/wqflask/marker_regression/marker_regression_gn1.py
@@ -1204,6 +1204,8 @@ class MarkerRegression(object):
else:
if self.mapping_method == "gemma" or self.mapping_method == "gemma_bimbam":
string2 = 'Using GEMMA mapping method with no control for other QTLs.'
+ if self.covariates != "":
+ string3 = 'Using following traits as covariates: ' + self.covariates
elif self.mapping_method == "rqtl_plink" or self.mapping_method == "rqtl_geno":
string2 = 'Using R/qtl mapping method with no control for other QTLs.'
elif self.mapping_method == "plink":
diff --git a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
index 50228b5e..6b58190f 100644
--- a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
+++ b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py
@@ -1,17 +1,20 @@
-def gen_reaper_results(this_trait, dataset, samples_before, json_data, num_perm, bootCheck, num_bootstrap, do_control, control_marker, manhattan_plot):
+import utility.logger
+logger = utility.logger.getLogger(__name__ )
+
+def gen_reaper_results(this_trait, dataset, samples_before, trait_vals, json_data, num_perm, bootCheck, num_bootstrap, do_control, control_marker, manhattan_plot):
genotype = dataset.group.read_genotype_file()
if manhattan_plot != True:
genotype = genotype.addinterval()
- samples, values, variances, sample_aliases = this_trait.export_informative()
-
trimmed_samples = []
trimmed_values = []
- for i in range(0, len(samples)):
- if this_trait.data[samples[i]].name in samples_before:
- trimmed_samples.append(samples[i])
- trimmed_values.append(values[i])
+ for i in range(0, len(samples_before)):
+ try:
+ trimmed_values.append(float(trait_vals[i]))
+ trimmed_samples.append(samples_before[i])
+ except:
+ pass
perm_output = []
bootstrap_results = []
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index 59e100d8..53c96591 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -10,6 +10,7 @@ import time
import math
import datetime
import collections
+import re
from pprint import pformat as pf
@@ -25,6 +26,7 @@ from db import webqtlDatabaseFunction
from flask import render_template
from utility import formatting
+from utility.type_checking import is_float, is_int, is_str, get_float, get_int, get_string
from utility.logger import getLogger
logger = getLogger(__name__ )
@@ -64,14 +66,26 @@ views.py).
else:
self.and_or = "and"
self.search_terms = kw['search_terms_and']
- self.search_term_exists = True
+ search = self.search_terms
+ # check for dodgy search terms
+ rx = re.compile(r'.*\W(href|http|sql|select|update)\W.*',re.IGNORECASE)
+ if rx.match(search):
+ logger.info("Regex failed search")
+ self.search_term_exists = False
+ return
+ else:
+ self.search_term_exists = True
+
self.results = []
- if kw['type'] == "Phenotypes": # split datatype on type field
+ type = kw.get('type')
+ if type == "Phenotypes": # split datatype on type field
dataset_type = "Publish"
- elif kw['type'] == "Genotypes":
+ elif type == "Genotypes":
dataset_type = "Geno"
else:
dataset_type = "ProbeSet" # ProbeSet is default
+
+ assert(is_str(kw.get('dataset')))
self.dataset = create_dataset(kw['dataset'], dataset_type)
logger.debug("search_terms:", self.search_terms)
self.search()
@@ -145,6 +159,7 @@ statement and executes
else:
combined_where_clause += "OR"
else:
+ logger.debug("Search failed 1")
self.search_term_exists = False
if self.search_term_exists:
combined_where_clause = "(" + combined_where_clause + ")"
@@ -155,6 +170,7 @@ statement and executes
else:
logger.debug("len(search_terms)<=1")
if self.search_terms == []:
+ logger.debug("Search failed 2")
self.search_term_exists = False
else:
for a_search in self.search_terms:
@@ -162,6 +178,7 @@ statement and executes
if the_search != None:
self.results.extend(the_search.run())
else:
+ logger.debug("Search failed 3")
self.search_term_exists = False
if self.search_term_exists:
diff --git a/wqflask/wqflask/static/dbdoc/TODO.md b/wqflask/wqflask/static/dbdoc/TODO.md
new file mode 100644
index 00000000..c0a8bab7
--- /dev/null
+++ b/wqflask/wqflask/static/dbdoc/TODO.md
@@ -0,0 +1 @@
+TODO: Add all database documentation into this folder
diff --git a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2.js b/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2.js
index 43ac6086..bf0a14e6 100644
--- a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2.js
+++ b/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2.js
@@ -1,6 +1,7 @@
var chart;
+var srchart;
-function drawg () {
+function drawg() {
//
chart = nv.models.scatterChart();
//
@@ -27,11 +28,45 @@ function drawg () {
chart.yAxis.tickFormat(d3.format(checkformat(yrange)));
//
chart.tooltip.contentGenerator(function (obj) {
- // return '<b style="font-size: 18px">(' + obj.point.x + ', ' + obj.point.y + ')</b>';
- return '<b style="font-size: 18px">' + obj.point.name + '</b>';
+ return tiptext(obj);
});
}
+function srdrawg() {
+ //
+ srchart = nv.models.scatterChart();
+ //
+ srchart.showLegend(false);
+ srchart.duration(300);
+ srchart.color(d3.scale.category10().range());
+ srchart.pointRange([0, 400]);
+ srchart.pointDomain([0, 10]);
+ //
+ srchart.xAxis.axisLabel(js_data.trait_1);
+ srchart.xAxis.axisLabelDistance(11);
+ srchart.yAxis.axisLabel(js_data.trait_2);
+ srchart.yAxis.axisLabelDistance(11);
+ //
+ xmin = d3.min(js_data.rdata[0]);
+ xmax = d3.max(js_data.rdata[0]);
+ xrange = xmax - xmin;
+ ymin = d3.min(js_data.rdata[1]);
+ ymax = d3.max(js_data.rdata[1]);
+ yrange = ymax - ymin;
+ srchart.xDomain([0, xmax + xrange/10]);
+ srchart.yDomain([0, ymax + yrange/10]);
+ srchart.xAxis.tickFormat(d3.format(checkformat(xrange)));
+ srchart.yAxis.tickFormat(d3.format(checkformat(yrange)));
+ //
+ srchart.tooltip.contentGenerator(function (obj) {
+ return tiptext(obj);
+ });
+}
+
+function tiptext(obj) {
+ return '<b style="font-size: 18px">' + obj.point.name + " (" + obj.point.x + ', ' + obj.point.y + ')</b>';
+}
+
function getdata(size, shape) {
var data = [];
data.push({
@@ -50,6 +85,25 @@ function getdata(size, shape) {
}
return data;
}
+
+function srgetdata(size, shape) {
+ var data = [];
+ data.push({
+ values: [],
+ slope: js_data.srslope,
+ intercept: js_data.srintercept
+ });
+ for (j = 0; j < js_data.rdata[0].length; j++) {
+ data[0].values.push({
+ x: js_data.rdata[0][j],
+ y: js_data.rdata[1][j],
+ name: js_data.indIDs[j],
+ size: size,
+ shape: shape
+ });
+ }
+ return data;
+}
function checkformat(range) {
cell = range / 10.0;
@@ -64,50 +118,47 @@ function checkformat(range) {
function chartupdate() {
//
- var axisxcolor = $("#axisxcolor").val();
- $(".nvd3 .nv-axis.nv-x text").css("fill", axisxcolor);
+ var labelcolor = $("#labelcolor").val();
+ $(".nvd3 .nv-axis.nv-x text").css("fill", labelcolor);
+ $(".nvd3 .nv-axis.nv-y text").css("fill", labelcolor);
//
- var axisycolor = $("#axisycolor").val();
- $(".nvd3 .nv-axis.nv-y text").css("fill", axisycolor);
+ var labelfont = $("#labelfont").val();
+ $(".nvd3 .nv-axis.nv-x text").css("font-size", labelfont);
+ $(".nvd3 .nv-axis.nv-y text").css("font-size", labelfont);
//
- var axisxfont = $("#axisxfont").val();
- $(".nvd3 .nv-axis.nv-x text").css("font-size", axisxfont);
+ var numbercolor = $("#numbercolor").val();
+ $("g.tick text").css("fill", numbercolor);
//
- var axisyfont = $("#axisyfont").val();
- $(".nvd3 .nv-axis.nv-y text").css("font-size", axisyfont);
+ var numberfont = $("#numberfont").val();
+ $("g.tick text").css("font-size", numberfont);
//
- var domainxcolor = $("#domainxcolor").val();
- $(".nv-x .nv-axis g path.domain").css("stroke", domainxcolor);
- //
- var domainycolor = $("#domainycolor").val();
- $(".nv-y .nv-axis g path.domain").css("stroke", domainycolor);
- //
- var domainxwidth = $("#domainxwidth").val();
- $(".nv-x .nv-axis g path.domain").css("stroke-width", domainxwidth);
+ var axiscolor = $("#axiscolor").val();
+ $(".nv-x .nv-axis g path.domain").css("stroke", axiscolor);
+ $(".nv-y .nv-axis g path.domain").css("stroke", axiscolor);
//
- var domainywidth = $("#domainywidth").val();
- $(".nv-y .nv-axis g path.domain").css("stroke-width", domainywidth);
+ var axiswidth = $("#axiswidth").val();
+ $(".nv-x .nv-axis g path.domain").css("stroke-width", axiswidth);
+ $(".nv-y .nv-axis g path.domain").css("stroke-width", axiswidth);
//
- var clinecolor = $("#clinecolor").val();
- $("line.nv-regLine").css("stroke", clinecolor);
+ var linecolor = $("#linecolor").val();
+ $("line.nv-regLine").css("stroke", linecolor);
//
- var clinewidth = $("#clinewidth").val();
- $("line.nv-regLine").css("stroke-width", clinewidth);
+ var linewidth = $("#linewidth").val();
+ $("line.nv-regLine").css("stroke-width", linewidth);
//
- var axiscolor = $("#axiscolor").val();
- $(".tick").css("stroke", axiscolor);
- //
- var axiswidth = $("#axiswidth").val();
- $("line.nv-regLine").css("stroke-width", axiswidth);
+ var markcolor = $("#markcolor").val();
+ $(".nvd3 g path").css("fill", markcolor);
}
function chartupdatewh() {
//
var width = $("#width").val();
$("#scatterplot2 svg").css("width", width);
+ $("#srscatterplot2 svg").css("width", width);
//
var height = $("#height").val();
$("#scatterplot2 svg").css("height", height);
+ $("#srscatterplot2 svg").css("height", height);
//
window.dispatchEvent(new Event('resize'));
}
@@ -118,7 +169,9 @@ function chartupdatedata() {
var shape = $("#markshape").val();
//
d3.select('#scatterplot2 svg').datum(nv.log(getdata(size, shape))).call(chart);
+ d3.select('#srscatterplot2 svg').datum(nv.log(srgetdata(size, shape))).call(srchart);
nv.utils.windowResize(chart.update);
+ nv.utils.windowResize(srchart.update);
}
function savesvg(svgEl, name) {
@@ -140,10 +193,14 @@ function saveassvg_pcs() {
savesvg($("#svg_pcs")[0], "Pearson Correlation Scatterplot.svg");
}
+function saveassvg_srcs() {
+ savesvg($("#svg_srcs")[0], "Spearman Rank Correlation Scatterplot.svg");
+}
+
drawg();
-chartupdate();
-chartupdatewh();
-chartupdatedata();
+srdrawg();
+
+
$(".chartupdate").change(function () {
chartupdate();
@@ -156,3 +213,10 @@ $(".chartupdatewh").change(function () {
$(".chartupdatedata").change(function () {
chartupdatedata();
});
+
+$(document).ready(function(){
+ //chartupdate();
+//chartupdatewh();
+chartupdatedata();
+//chartupdate();
+}); \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2_sr.js b/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2_sr.js
deleted file mode 100644
index d0392dd7..00000000
--- a/wqflask/wqflask/static/new/javascript/draw_corr_scatterplot-2_sr.js
+++ /dev/null
@@ -1,137 +0,0 @@
-var srchart;
-
-function srdrawg () {
- //
- srchart = nv.models.scatterChart();
- //
- srchart.showLegend(false);
- srchart.duration(300);
- srchart.color(d3.scale.category10().range());
- srchart.pointRange([0, 400]);
- srchart.pointDomain([0, 10]);
- //
- srchart.xAxis.axisLabel(js_data.trait_1);
- srchart.xAxis.axisLabelDistance(11);
- srchart.yAxis.axisLabel(js_data.trait_2);
- srchart.yAxis.axisLabelDistance(11);
- //
- xmin = d3.min(js_data.rdata[0]);
- xmax = d3.max(js_data.rdata[0]);
- xrange = xmax - xmin;
- ymin = d3.min(js_data.rdata[1]);
- ymax = d3.max(js_data.rdata[1]);
- yrange = ymax - ymin;
- srchart.xDomain([0, xmax + xrange/10]);
- srchart.yDomain([0, ymax + yrange/10]);
- srchart.xAxis.tickFormat(d3.format(srcheckformat(xrange)));
- srchart.yAxis.tickFormat(d3.format(srcheckformat(yrange)));
- //
- srchart.tooltip.contentGenerator(function (obj) {
- // return '<b style="font-size: 18px">(' + obj.point.x + ', ' + obj.point.y + ')</b>';
- return '<b style="font-size: 18px">' + obj.point.name + '</b>';
- });
-}
-
-function srgetdata(size, shape) {
- var data = [];
- data.push({
- values: [],
- slope: js_data.srslope,
- intercept: js_data.srintercept
- });
- for (j = 0; j < js_data.rdata[0].length; j++) {
- data[0].values.push({
- x: js_data.rdata[0][j],
- y: js_data.rdata[1][j],
- name: js_data.indIDs[j],
- size: size,
- shape: shape
- });
- }
- return data;
-}
-
-function srcheckformat(range) {
- cell = range / 10.0;
- if (cell >= 1) {
- return ",r";
- } else {
- cell = -Math.log(cell);
- n = cell.toString().split(".")[0].length;
- return ",.0" + n + "f";
- }
-}
-
-function srchartupdate() {
- //
- var axisxcolor = $("#axisxcolor").val();
- $(".nvd3 .nv-axis.nv-x text").css("fill", axisxcolor);
- //
- var axisycolor = $("#axisycolor").val();
- $(".nvd3 .nv-axis.nv-y text").css("fill", axisycolor);
- //
- var axisxfont = $("#axisxfont").val();
- $(".nvd3 .nv-axis.nv-x text").css("font-size", axisxfont);
- //
- var axisyfont = $("#axisyfont").val();
- $(".nvd3 .nv-axis.nv-y text").css("font-size", axisyfont);
- //
- var domainxcolor = $("#domainxcolor").val();
- $(".nv-x .nv-axis g path.domain").css("stroke", domainxcolor);
- //
- var domainycolor = $("#domainycolor").val();
- $(".nv-y .nv-axis g path.domain").css("stroke", domainycolor);
- //
- var domainxwidth = $("#domainxwidth").val();
- $(".nv-x .nv-axis g path.domain").css("stroke-width", domainxwidth);
- //
- var domainywidth = $("#domainywidth").val();
- $(".nv-y .nv-axis g path.domain").css("stroke-width", domainywidth);
- //
- var clinecolor = $("#clinecolor").val();
- $("line.nv-regLine").css("stroke", clinecolor);
- //
- var clinewidth = $("#clinewidth").val();
- $("line.nv-regLine").css("stroke-width", clinewidth);
-}
-
-function srchartupdatewh() {
- //
- var width = $("#srwidth").val();
- $("#srscatterplot2 svg").css("width", width);
- //
- var height = $("#srheight").val();
- $("#srscatterplot2 svg").css("height", height);
- //
- window.dispatchEvent(new Event('resize'));
-}
-
-function srchartupdatedata() {
- //
- var size = $("#srmarksize").val();
- var shape = $("#srmarkshape").val();
- //
- d3.select('#srscatterplot2 svg').datum(nv.log(srgetdata(size, shape))).call(srchart);
- nv.utils.windowResize(srchart.update);
-}
-
-function saveassvg_srcs() {
- savesvg($("#svg_srcs")[0], "Spearman Rank Correlation Scatterplot.svg");
-}
-
-srdrawg();
-srchartupdate();
-srchartupdatewh();
-srchartupdatedata();
-
-$(".srchartupdate").change(function () {
- srchartupdate();
-});
-
-$(".srchartupdatewh").change(function () {
- srchartupdatewh();
-});
-
-$(".srchartupdatedata").change(function () {
- srchartupdatedata();
-});
diff --git a/wqflask/wqflask/static/new/javascript/get_covariates_from_collection.js b/wqflask/wqflask/static/new/javascript/get_covariates_from_collection.js
index 92e2b13b..f2e694d8 100644
--- a/wqflask/wqflask/static/new/javascript/get_covariates_from_collection.js
+++ b/wqflask/wqflask/static/new/javascript/get_covariates_from_collection.js
@@ -24,6 +24,7 @@ collection_click = function() {
submit_click = function() {
var covariates_string = "";
+ var covariates_display_string = "";
$('#collections_holder').find('input[type=checkbox]:checked').each(function() {
var this_dataset, this_trait;
this_trait = $(this).parents('tr').find('.trait').text();
@@ -31,12 +32,15 @@ submit_click = function() {
this_dataset = $(this).parents('tr').find('.dataset').text();
console.log("this_dataset is:", this_dataset);
covariates_string += this_trait + ":" + this_dataset + ","
+ covariates_display_string += this_trait + "\n"
});
// Trim the last comma
covariates_string = covariates_string.substring(0, covariates_string.length - 1)
+ //covariates_display_string = covariates_display_string.substring(0, covariates_display_string.length - 2)
console.log("COVARIATES:", covariates_string)
$("input[name=covariates]").val(covariates_string)
+ $(".selected_covariates").val(covariates_display_string)
return $.colorbox.close();
};
@@ -46,6 +50,7 @@ trait_click = function() {
trait = $(this).parent().find('.trait').text();
dataset = $(this).parent().find('.dataset').text();
$("input[name=covariates]").val(trait + ":" + dataset)
+ $(".selected_covariates").text(trait)
return $.colorbox.close();
};
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js
index 099d8010..df10c060 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait.js
@@ -88,7 +88,8 @@
};
})(this));
$("#remove_covariates").click(function () {
- $("input[name=covariates]").val("")
+ $("input[name=covariates]").val("")
+ $(".selected_covariates").val("")
});
d3.select("#clear_compare_trait").on("click", (function(_this) {
return function() {
diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html
index ad72052e..e7f3229b 100644
--- a/wqflask/wqflask/templates/collections/list.html
+++ b/wqflask/wqflask/templates/collections/list.html
@@ -26,13 +26,13 @@
{% endif %}
</div>
<div>
- <form id="collections_form" action="/delete" method="post">
- <input type="hidden" name="uc_id" id="uc_id" value="" />
- </form>
+ <form id="collections_form" action="/delete" method="post">
+ <input type="hidden" name="uc_id" id="uc_id" value="" />
+ </form>
<button class="btn btn-default" id="select_all"><span class="glyphicon glyphicon-ok"></span> Select All</button>
<button class="btn btn-default" id="deselect_all"><span class="glyphicon glyphicon-remove"></span> Deselect All</button>
<button class="btn btn-default" id="invert"><span class="glyphicon glyphicon-resize-vertical"></span> Invert</button>
- <button class="btn btn-danger" id="remove_collections" data-url="/collections/delete">Remove Collections</button>
+ <button class="btn btn-danger" id="remove_collections" data-url="/collections/delete">Remove Collections</button>
</div>
<br>
<div id="collections_list" style="width:50%;">
@@ -51,7 +51,11 @@
<tbody>
{% for uc in collections %}
<tr class="collection_line">
+ {% if g.user_session.user_ob %}
<td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.id }}"></td>
+ {% else %}
+ <td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;"><INPUT TYPE="checkbox" NAME="collection" class="checkbox trait_checkbox" VALUE="{{ uc.name }}"></td>
+ {% endif %}
<td align="right">{{ loop.index }}
{% if g.user_session.user_ob %}
<td><a class="collection_name" href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td>
diff --git a/wqflask/wqflask/templates/corr_scatterplot.html b/wqflask/wqflask/templates/corr_scatterplot.html
index fb2bd55c..bb509270 100644
--- a/wqflask/wqflask/templates/corr_scatterplot.html
+++ b/wqflask/wqflask/templates/corr_scatterplot.html
@@ -75,72 +75,16 @@
<table class="table">
<tr>
-
- <td>Axis X Color</td>
- <td><input class="chartupdate" id="axisxcolor" type="color" value="#000000"></td>
-
- <td>Axis X Font</td>
- <td><input class="chartupdate" id="axisxfont" type="text" value="16" style="width: 44px;"> px</td>
-
- <td>Domain X Color</td>
- <td><input class="chartupdate" id="domainxcolor" type="color" value="#000000"></td>
-
- <td>Domain X Width</td>
- <td><input class="chartupdate" id="domainxwidth" type="text" value="2" style="width: 44px;"> px</td>
-
- <td>Correlation Line Color</td>
- <td><input class="chartupdate" id="clinecolor" type="color" value="#000000"></td>
-
- <td>Axis Line Color</td>
- <td><input class="chartupdate" id="axiscolor" type="color" value="#000000"></td>
-
- </tr>
- <tr>
-
- <td>Axis Y Color</td>
- <td><input class="chartupdate" id="axisycolor" type="color" value="#000000"></td>
-
- <td>Axis Y Font</td>
- <td><input class="chartupdate" id="axisyfont" type="text" value="16" style="width: 44px;"> px</td>
-
- <td>Domain Y Color</td>
- <td><input class="chartupdate" id="domainycolor" type="color" value="#000000"></td>
-
- <td>Domain Y Width</td>
- <td><input class="chartupdate" id="domainywidth" type="text" value="2" style="width: 44px;"> px</td>
-
- <td>Correlation Line Width</td>
- <td><input class="chartupdate" id="clinewidth" type="text" value="1" style="width: 44px;"> px</td>
-
- <td>Axis Line Width</td>
- <td><input class="chartupdate" id="axiswidth" type="text" value="1" style="width: 44px;"> px</td>
-
- </tr>
+ <td style="vertical-align: middle;">Width <input class="chartupdatewh" id="width" type="text" value="1000" style="width: 44px; height: 22px;"> px</td>
+ <td style="vertical-align: middle;">Height <input class="chartupdatewh" id="height" type="text" value="800" style="width: 44px; height: 22px;"> px</td>
+ </tr>
</table>
-<br>
-
-<ul class="nav nav-tabs">
- <li class="active"><a href="#tp1" data-toggle="tab">Pearson</a></li>
- <li> <a href="#tp2" data-toggle="tab">Spearman Rank</a></li>
-</ul>
-
-<div class="tab-content">
- <div class="tab-pane active" id="tp1">
-
-<br>
<table class="table">
- <tr>
-
- <td>Width</td>
- <td><input class="chartupdatewh" id="width" type="text" value="1000" style="width: 44px;"> px</td>
-
- <td>Height</td>
- <td><input class="chartupdatewh" id="height" type="text" value="800" style="width: 44px;"> px</td>
-
- <td>Size</td>
- <td>
- <select class="chartupdatedata" id="marksize" style="width: 100px;">
+ <tr>
+ <td style="vertical-align: middle;">Mark
+ <input class="chartupdate" id="markcolor" type="color" value="#8fbbda">
+ <select class="chartupdatedata" id="marksize" style="width: 44px; height: 22px;">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
@@ -152,12 +96,12 @@
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
+ <option value="15">15</option>
+ <option value="20">20</option>
+ <option value="25">25</option>
+ <option value="30">30</option>
</select>
- </td>
-
- <td>Shape</td>
- <td>
- <select class="chartupdatedata" id="markshape" style="width: 100px;">
+ <select class="chartupdatedata" id="markshape" style="width: 100px; height: 22px;">
<option value="circle" selected>Circle</option>
<option value="cross">Cross</option>
<option value="triangle-up">Triangle-up</option>
@@ -166,23 +110,47 @@
<option value="square">Square</option>
</select>
</td>
-
- </tr>
+ </tr>
</table>
-<div><a id="a_svg_pcs" href="#" onclick="javascript:saveassvg_pcs();" class="btn btn-primary">Save as SVG</a></div>
+<table class="table">
+ <tr>
+ <td style="vertical-align: middle;">Label
+ <input class="chartupdate" id="labelcolor" type="color" value="#000000">
+ <input class="chartupdate" id="labelfont" type="text" value="16" style="width: 44px; height: 22px;"> px
+ </td>
+ <td style="vertical-align: middle;">Number
+ <input class="chartupdate" id="numbercolor" type="color" value="#000000">
+ <input class="chartupdate" id="numberfont" type="text" value="16" style="width: 44px; height: 22px;"> px
+ </td>
+ <td style="vertical-align: middle;">Axis
+ <input class="chartupdate" id="axiscolor" type="color" value="#000000">
+ <input class="chartupdate" id="axiswidth" type="text" value="2" style="width: 44px; height: 22px;"> px
+ </td>
+ <td style="vertical-align: middle;">Line
+ <input class="chartupdate" id="linecolor" type="color" value="#8fbbda">
+ <input class="chartupdate" id="linewidth" type="text" value="1" style="width: 44px; height: 22px;"> px
+ </td>
+ </tr>
+</table>
-<div style="width: 1000px; text-align: center;"><h2>Pearson Correlation Scatterplot</h2></div>
+<br>
-<div id="scatterplot2">
- <svg id="svg_pcs" style="width: 1000px; height: 800px; margin-left: 10px;"></svg>
-</div>
+<ul class="nav nav-tabs">
+ <li class="active"><a href="#tp1" data-toggle="tab">Pearson</a></li>
+ <li> <a href="#tp2" data-toggle="tab">Spearman Rank</a></li>
+</ul>
+
+<div class="tab-content">
+ <div class="tab-pane active" id="tp1">
<br>
-<div class="alert alert-info" style="width: 200px; margin-left: 80px;">
- y = {{'%0.3f' % jsdata.slope}} * x + {{'%0.3f' % jsdata.intercept}}
-</div>
+<div><a id="a_svg_pcs" href="#" onclick="javascript:saveassvg_pcs();" class="btn btn-primary">Save as SVG</a></div>
+
+<div style="width: 1000px; text-align: center;"><h2>Pearson Correlation Scatterplot</h2></div>
+
+<div id="scatterplot2"><svg id="svg_pcs" style="width: 1000px; height: 800px; margin-left: 10px;"></svg></div>
<br>
@@ -196,6 +164,13 @@
<tr><td>Intercept</td> <td>{{'%0.3f' % jsdata.intercept}}</td></tr>
<tr><td>r value</td> <td>{{'%0.3f' % jsdata.r_value}}</td></tr>
<tr><td>P value</td> <td>{% if jsdata.p_value < 0.001 %}{{'%0.3e' % jsdata.p_value}}{% else %}{{'%0.3f' % jsdata.p_value}}{% endif %}</td></tr>
+ <tr>
+ <td style="text-align: left;" colspan="2">
+ Regression Line
+ <br>
+ y = {{'%0.3f' % jsdata.slope}} * x + {{'%0.3f' % jsdata.intercept}}
+ </td>
+ </tr>
</tbody>
</table>
@@ -204,54 +179,12 @@
<div class="tab-pane" id="tp2">
<br>
-<table class="table">
- <tr>
-
- <td>Width</td>
- <td><input class="srchartupdatewh" id="srwidth" type="text" value="1000" style="width: 44px;"> px</td>
-
- <td>Height</td>
- <td><input class="srchartupdatewh" id="srheight" type="text" value="800" style="width: 44px;"> px</td>
-
- <td>Size</td>
- <td>
- <select class="srchartupdatedata" id="srmarksize" style="width: 100px;">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- <option value="3">3</option>
- <option value="4">4</option>
- <option value="5" selected>5</option>
- <option value="6">6</option>
- <option value="7">7</option>
- <option value="8">8</option>
- <option value="9">9</option>
- <option value="10">10</option>
- </select>
- </td>
-
- <td>Shape</td>
- <td>
- <select class="srchartupdatedata" id="srmarkshape" style="width: 100px;">
- <option value="circle" selected>Circle</option>
- <option value="cross">Cross</option>
- <option value="triangle-up">Triangle-up</option>
- <option value="triangle-down">Triangle-down</option>
- <option value="diamond">Diamond</option>
- <option value="square">Square</option>
- </select>
- </td>
-
- </tr>
-</table>
<div><a id="a_svg_srcs" href="#" onclick="javascript:saveassvg_srcs();" class="btn btn-primary">Save as SVG</a></div>
<div style="width: 1000px; text-align: center;"><h2>Spearman Rank Correlation Scatterplot</h2></div>
-<div id="srscatterplot2">
- <svg id="svg_srcs" style="width: 1000px; height: 800px; margin-left: 10px;"></svg>
-</div>
+<div id="srscatterplot2"><svg id="svg_srcs" style="width: 1000px; height: 800px; margin-left: 10px;"></svg></div>
<br>
@@ -287,5 +220,4 @@
<script language="javascript" type="text/javascript" src="/static/new/javascript/colorbrewer.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/panelutil.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/draw_corr_scatterplot-2.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/draw_corr_scatterplot-2_sr.js"></script>
{% endblock %}
diff --git a/wqflask/wqflask/templates/correlation_matrix.html b/wqflask/wqflask/templates/correlation_matrix.html
index ab793d58..d27788a8 100644
--- a/wqflask/wqflask/templates/correlation_matrix.html
+++ b/wqflask/wqflask/templates/correlation_matrix.html
@@ -61,6 +61,7 @@
<br>
<button class="btn btn-default" id="short_labels">Short Labels</button>
<button class="btn btn-default" id="long_labels">Long Labels</button>
+{% if pca_works == "True" %}
<br>
<br>
<h2>Factor Loadings Plot</h2>
@@ -93,7 +94,7 @@
</tbody>
</table>
</div>
-
+{% endif %}
{% endblock %}
{% block js %}
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index fa9e3585..fb4e19a1 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -1,8 +1,7 @@
{% extends "base.html" %}
{% block css %}
+ <link rel="stylesheet" type="text/css" href="/static/new/packages/tabulator/css/tabulator.css" />
<link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
- <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
- <link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" />
<link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/extensions/buttons.bootstrap.css" />
{% endblock %}
{% block content %}
@@ -63,15 +62,15 @@
</div>
<div style="width: {% if target_dataset.type == "ProbeSet" %}1600px{% elif target_dataset.type == "Publish" %}1400px{% else %}800px{% endif %};">
- <table id="trait_table" class="display dataTable nowrap" style="float: left;">
+ <table id="trait_table" class="display dataTable nowrap" style="font-size: 12px; float: left;">
<thead>
<tr>
- <th style="width: 30px;"></th>
+ <th></th>
{% for header in target_dataset.header_fields %}
{% if header == 'Year' %}
<th>{{header}}</th>
{% elif header == 'Max LRS' %}
- <th>Max LRS<a href="http://genenetwork.org//glossary.html#L" target="_blank"><sup style="color:#f00"> ?</sup></a></th>
+ <th>Max LRS</th>
{% elif header == 'Max LRS Location' %}
<th>{{header}}</th>
{% elif header == 'Location' %}
@@ -79,7 +78,7 @@
{% elif header == 'Mean' %}
<th>{{header}}</th>
{% elif header == 'Additive Effect' %}
- <th>Additive Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a></th>
+ <th>Additive Effect</th>
{% elif header == 'Index' %}
<th>{{header}}</th>
{% elif header == 'N' %}
@@ -91,7 +90,7 @@
{% if target_dataset.type == "ProbeSet" %}
{% if corr_method == 'pearson' %}
<th>Sample r</th>
- <th>&nbsp;&nbsp;N</th>
+ <th>N</th>
<th>Sample p(r)</th>
<th>Lit r</th>
<th>Tissue r</th>
@@ -129,8 +128,8 @@
<tbody>
{% for trait in correlation_results %}
<tr>
- <td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;"><INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" style="padding-right: 0px;" VALUE="{{ data_hmac('{}:{}'.format(trait.name, trait.dataset.name)) }}"></td>
- <td align="right">{{ loop.index }}</td>
+ <td><INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" style="padding-right: 0px;" VALUE="{{ data_hmac('{}:{}'.format(trait.name, trait.dataset.name)) }}"></td>
+ <td style="padding-left: 8px; padding-right: 0px; padding-top: 4px; align: center;">{{ loop.index }}</td>
<td>
<a href="{{ url_for('show_trait_page',
trait_id = trait.name,
@@ -191,13 +190,15 @@
{% block js %}
<script type="text/javascript" src="/static/new/javascript/search_results.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/new/js_external/jszip.min.js"></script>
+ <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
+
<script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.js"></script>
<script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js"></script>
<script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.html5.min.js"></script>
<script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.bootstrap.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/js_external/jszip.min.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/dataTables.naturalSort.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
+
<script type="text/javascript" charset="utf-8">
function getValue(x) {
if (x.indexOf('input') >= 0) {
@@ -213,7 +214,8 @@
}
return parseFloat(x);
}
-
+
+
jQuery.fn.dataTableExt.oSort['numeric-html-asc'] = function(a,b) {
a = Math.abs(parseFloat($(a).text()));
b = Math.abs(parseFloat($(b).text()));
@@ -263,6 +265,8 @@
$(document).ready( function () {
+ var table_json = {{ json_results | safe }}
+
$('#trait_table tr').click(function(event) {
if (event.target.type !== 'checkbox') {
$(':checkbox', this).trigger('click');
diff --git a/wqflask/wqflask/templates/empty_collection.html b/wqflask/wqflask/templates/empty_collection.html
new file mode 100644
index 00000000..d1b779ef
--- /dev/null
+++ b/wqflask/wqflask/templates/empty_collection.html
@@ -0,0 +1,15 @@
+{% extends "base.html" %}
+{% block title %}{{ tool }}{% endblock %}
+{% block content %}
+<!-- Start of body -->
+ {{ header("Error") }}
+
+ <div class="container">
+ <input type="hidden" name="uc_id" id="uc_id" value="{{ uc_id }}">
+ <p>You must select at least two traits to use the {{ tool }}.</p>
+ </div>
+
+
+<!-- End of body -->
+
+{% endblock %}
diff --git a/wqflask/wqflask/templates/new_security/login_user.html b/wqflask/wqflask/templates/new_security/login_user.html
index 0dae3503..949760b6 100644
--- a/wqflask/wqflask/templates/new_security/login_user.html
+++ b/wqflask/wqflask/templates/new_security/login_user.html
@@ -15,7 +15,6 @@
<h4>Don't have an account?</h4>
-
{% if es_server: %}
<a href="/n/register" class="btn btn-primary modalize">Create a new account</a>
{% else: %}
@@ -88,10 +87,17 @@
</form>
{% else: %}
<div class="alert alert-warning">
- <p>You cannot login at this moment using your GeneNetwork account.<br />
+ <p>You cannot login at this moment using your GeneNetwork account (the authentication service is down).<br />
Please try again later.</p>
</div>
{% endif %}
+ {% if not es_server and not external_login: %}
+ <hr>
+ <div class="alert alert-warning">
+ Note: it is safe to use GeneNetwork without a login. Login is only required for keeping track of
+ collections and getting access to some types of restricted data.
+ </div>
+ {% endif %}
</div>
</div>
diff --git a/wqflask/wqflask/templates/show_trait_calculate_correlations.html b/wqflask/wqflask/templates/show_trait_calculate_correlations.html
index c5f815ce..ef233333 100644
--- a/wqflask/wqflask/templates/show_trait_calculate_correlations.html
+++ b/wqflask/wqflask/templates/show_trait_calculate_correlations.html
@@ -1,9 +1,10 @@
<div>
+ <div class="col-xs-7">
<div style="padding: 20px" class="form-horizontal">
<div class="form-group">
- <label for="corr_type" class="col-xs-1 control-label">Method</label>
- <div class="col-xs-2 controls">
+ <label for="corr_type" class="col-xs-2 control-label">Method</label>
+ <div class="col-xs-3 controls">
<select name="corr_type" class="form-control">
<option value="sample">Sample r</option>
<option value="lit">Literature r</option>
@@ -13,8 +14,8 @@
</div>
<div class="form-group">
- <label for="corr_dataset" class="col-xs-1 control-label">Database</label>
- <div class="col-xs-6 controls">
+ <label for="corr_dataset" class="col-xs-2 control-label">Database</label>
+ <div class="col-xs-10 controls">
<select name="corr_dataset" class="form-control">
{% for tissue in corr_tools.dataset_menu %}
{% if tissue.tissue %}
@@ -37,8 +38,8 @@
</div>
<div class="form-group">
- <label for="corr_return_results" class="col-xs-1 control-label">Return</label>
- <div class="col-xs-2 controls">
+ <label for="corr_return_results" class="col-xs-2 control-label">Return</label>
+ <div class="col-xs-3 controls">
<select name="corr_return_results" class="form-control">
{% for return_result in corr_tools.return_results_menu %}
<option value="{{ return_result }}"
@@ -53,8 +54,8 @@
</div>
<div class="form-group">
- <label for="corr_samples_group" class="col-xs-1 control-label">Samples</label>
- <div class="col-xs-2 controls">
+ <label for="corr_samples_group" class="col-xs-2 control-label">Samples</label>
+ <div class="col-xs-3 controls">
<select name="corr_samples_group" class="form-control">
{% for group, pretty_group in sample_group_types.items() %}
<option value="{{ group }}">{{ pretty_group }}</option>
@@ -64,8 +65,8 @@
</div>
<div id="corr_sample_method" class="form-group">
- <label for="corr_sample_method" class="col-xs-1 control-label">Type</label>
- <div class="col-xs-2 controls">
+ <label for="corr_sample_method" class="col-xs-2 control-label">Type</label>
+ <div class="col-xs-3 controls">
<select name="corr_sample_method" class="form-control">
<option value="pearson">Pearson</option>
<option value="spearman">Spearman Rank</option>
@@ -73,14 +74,14 @@
</div>
</div>
<div class="form-group">
- <label class="col-xs-1 control-label">Min Expr</label>
- <div class="col-xs-2 controls">
+ <label class="col-xs-2 control-label">Min Expr</label>
+ <div class="col-xs-3 controls">
<input name="min_expr" value="" type="text" class="form-control" style="width: 50px;">
</div>
</div>
<div class="form-group">
- <label class="col-xs-1 control-label">Location</label>
- <div class="col-xs-4 controls">
+ <label class="col-xs-2 control-label">Location</label>
+ <div class="col-xs-5 controls">
<span>
Chr: <input name="loc_chr" value="" type="text" class="form-control" style="width: 50px; display: inline;">&nbsp;&nbsp;&nbsp;
Mb: <input name="min_loc_mb" value="" type="text" class="form-control" style="width: 50px; display: inline;"> &nbsp;to&nbsp; <input name="max_loc_mb" value="" type="text" class="form-control" style="width: 50px; display: inline;">
@@ -89,8 +90,8 @@
</div>
</div>
<div class="form-group">
- <label class="col-xs-1 control-label">Range</label>
- <div class="col-xs-4 controls">
+ <label class="col-xs-2 control-label">Range</label>
+ <div class="col-xs-5 controls">
<input name="p_range_lower" value="" type="hidden">
<input name="p_range_upper" value="" type="hidden">
<span style="display: inline;">
@@ -103,48 +104,45 @@
</div>
<div class="form-group">
- <label for="corr_sample_method" class="col-xs-1 control-label"></label>
- <div class="col-xs-4 controls">
+ <label for="corr_sample_method" class="col-xs-2 control-label"></label>
+ <div class="col-xs-3 controls">
<button class="btn corr_compute submit_special btn-success" data-url="/corr_compute" title="Compute Correlation">
<i class="icon-ok-circle icon-white"></i> Compute
</button>
</div>
</div>
-
- <div class="form-group">
- <label for="descriptions" class="col-xs-1 control-label"></label>
- <div class="col-xs-6 controls">
- <span id="sample_r_desc" class="correlation_desc fs12">
- The <a href="http://genenetwork.org/correlationAnnotation.html#genetic_r">Sample Correlation</a>
- is computed
- between trait data and any
- other traits in the sample database selected above. Use
- <a href="http://www.genenetwork.org/glossary.html#Correlations">Spearman
- Rank</a>
- when the sample size is small (&lt;20) or when there are influential outliers.
- </span>
- <span id="lit_r_desc" style="display: none;" class="correlation_desc fs12">
- The <a href="http://genenetwork.org/correlationAnnotation.html#literatureCorr">Literature Correlation</a>
- (Lit r) between
- this gene and all other genes is computed<br>
- using the <a href="https://grits.eecs.utk.edu/sgo/sgo.html">
- Semantic Gene Organizer</a>
- and human, rat, and mouse data from PubMed.
- Values are ranked by Lit r, but Sample r and Tissue r are also displayed.<br>
- <a href="http://genenetwork.org/glossary.html#Literature">More on using Lit r</a>
- </span>
- <span id="tissue_r_desc" style="display: none;" class="correlation_desc fs12">
- The <a href="http://genenetwork.org/webqtl/main.py?FormID=tissueCorrelation">Tissue Correlation</a>
- (Tissue r)
- estimates the similarity of expression of two genes
- or transcripts across different cells, tissues, or organs
- (<a href="http://genenetwork.org/correlationAnnotation.html#tissueCorr">glossary</a>).
- Tissue correlations
- are generated by analyzing expression in multiple samples usually taken from single cases.<br>
- <strong>Pearson</strong> and <strong>Spearman Rank</strong> correlations have been
- computed for all pairs of genes using data from mouse samples.<br>
- </span>
- </div>
- </div>
</div>
+ </div>
+ <div class="col-xs-5">
+ <span id="sample_r_desc" class="correlation_desc fs12">
+ The <a href="http://genenetwork.org/correlationAnnotation.html#genetic_r">Sample Correlation</a>
+ is computed
+ between trait data and any
+ other traits in the sample database selected above. Use
+ <a href="http://www.genenetwork.org/glossary.html#Correlations">Spearman
+ Rank</a>
+ when the sample size is small (&lt;20) or when there are influential outliers.
+ </span>
+ <span id="lit_r_desc" style="display: none;" class="correlation_desc fs12">
+ The <a href="http://genenetwork.org/correlationAnnotation.html#literatureCorr">Literature Correlation</a>
+ (Lit r) between
+ this gene and all other genes is computed<br>
+ using the <a href="https://grits.eecs.utk.edu/sgo/sgo.html">
+ Semantic Gene Organizer</a>
+ and human, rat, and mouse data from PubMed.
+ Values are ranked by Lit r, but Sample r and Tissue r are also displayed.<br>
+ <a href="http://genenetwork.org/glossary.html#Literature">More on using Lit r</a>
+ </span>
+ <span id="tissue_r_desc" style="display: none;" class="correlation_desc fs12">
+ The <a href="http://genenetwork.org/webqtl/main.py?FormID=tissueCorrelation">Tissue Correlation</a>
+ (Tissue r)
+ estimates the similarity of expression of two genes
+ or transcripts across different cells, tissues, or organs
+ (<a href="http://genenetwork.org/correlationAnnotation.html#tissueCorr">glossary</a>).
+ Tissue correlations
+ are generated by analyzing expression in multiple samples usually taken from single cases.<br>
+ <strong>Pearson</strong> and <strong>Spearman Rank</strong> correlations have been
+ computed for all pairs of genes using data from mouse samples.<br>
+ </span>
+ </div>
</div> \ No newline at end of file
diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html
index dcec2b9e..03590c2c 100644
--- a/wqflask/wqflask/templates/show_trait_mapping_tools.html
+++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html
@@ -1,6 +1,6 @@
<div>
- {% if (use_pylmm_rqtl and dataset.group.species != "human") or use_plink_gemma %}
- <div class="col-xs-4">
+ {% if dataset.group.mapping_names|length > 0 %}
+ <div class="col-xs-5">
<div class="tabbable"> <!-- Only required for left/right tabs -->
<ul class="nav nav-pills">
@@ -38,11 +38,11 @@
{# if use_pylmm_rqtl and not use_plink_gemma and dataset.group.species != "human" #}
{% if dataset.group.mapping_id == "1" %}
<div class="tab-pane active" id="gemma">
- <div style="padding-top: 10px;" class="form-horizontal">
+ <div style="padding-top: 20px;" class="form-horizontal">
{% if genofiles and genofiles|length>0 %}
<div class="mapping_method_fields form-group">
- <label for="genofiles" class="col-xs-3 control-label">Genotypes</label>
- <div style="margin-left: 20px;" class="col-xs-8 controls">
+ <label for="genofiles" style="text-align: right;" class="col-xs-3 control-label">Genotypes</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<select id="genofile_gemma" class="form-control">
{% for item in genofiles %}
<option value="{{item['location']}}:{{item['title']}}">{{item['title']}}</option>
@@ -52,50 +52,72 @@
</div>
{% endif %}
<div class="mapping_method_fields form-group">
- <label for="maf_gemma" class="col-xs-5 control-label">Minor allele threshold</label>
- <div style="margin-left: 20px;" class="col-xs-3 controls">
+ <label for="maf_gemma" style="text-align: right;" class="col-xs-3 control-label">MAF</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<input name="maf_gemma" value="0.01" type="text" class="form-control">
</div>
</div>
<div class="mapping_method_fields form-group">
- <label class="col-xs-4 control-label">Use LOCO</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" class="col-xs-3 control-label">Use LOCO</label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
<label class="radio-inline">
- <input type="radio" name="use_loco" value="True">
+ <input type="radio" name="use_loco" value="True" checked="">
Yes
</label>
<label class="radio-inline">
- <input type="radio" name="use_loco" value="False" checked="">
+ <input type="radio" name="use_loco" value="False">
No
</label>
</div>
</div>
+ <!--
</div>
<div style="padding-top: 5px; padding-bottom: 5px; padding-left: 20px;" class="form-horizontal">
+ -->
<div class="mapping_method_fields form-group">
- <button type="button" id="select_covariates" class="btn btn-default">
- Select Covariates
- </button>
- <button type="button" id="remove_covariates" class="btn btn-default">
- Remove Covariates
+ <label style="text-align: right;" class="col-xs-3 control-label">Covariates</label>
+ <div style="margin-left:20px;" class="col-xs-7">
+ {% if g.user_session.user_ob and (g.user_session.user_ob.display_num_collections() == "") %}
+ No collections available. Please add traits to a collection to use them as covariates.
+ {% elif g.cookie_session.display_num_collections() == "" %}
+ No collections available. Please add traits to a collection to use them as covariates.
+ {% else %}
+ <div style="margin-bottom: 10px;" class="btn-group" role="group">
+ <button type="button" id="select_covariates" class="btn btn-default">Select</button>
+ <button type="button" id="remove_covariates" class="btn btn-default">Remove</button>
+ </div>
+ <textarea rows="3" cols="20" readonly placeholder="No covariates selected" style="overflow-y: scroll; resize: none;" class="selected_covariates"></textarea>
+ {% endif %}
+ </div>
+ </div>
+ <div class="mapping_method_fields form-group">
+ <label class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6">
+ <button id="gemma_bimbam_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Marker Regression">
+ Compute
</button>
+ </div>
</div>
</div>
-
+<!--
<div class="form-group">
<div class="col-xs-4 controls">
+ <label class="col-xs-2 control-label"></label>
+ <div class="col-xs-4">
<button id="gemma_bimbam_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Marker Regression">
Compute
</button>
+ </div>
</div>
</div>
+-->
</div>
<div class="tab-pane" id="interval_mapping">
<div style="margin-top: 20px" class="form-horizontal">
{% if genofiles and genofiles|length>0 %}
<div class="mapping_method_fields form-group">
- <label for="genofiles" class="col-xs-3 control-label">Genotypes</label>
- <div style="margin-left: 20px;" class="col-xs-8 controls">
+ <label style="text-align: right;" for="genofiles" class="col-xs-3 control-label">Genotypes</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<select id="genofile_reaper" class="form-control">
{% for item in genofiles %}
<option value="{{item['location']}}:{{item['title']}}">{{item['title']}}</option>
@@ -105,20 +127,20 @@
</div>
{% endif %}
<div class="mapping_method_fields form-group">
- <label for="mapping_permutations" class="col-xs-3 control-label">Permutations</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" for="mapping_permutations" class="col-xs-3 control-label">Permutations</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<input name="num_perm_reaper" value="2000" type="text" class="form-control">
</div>
</div>
<div class="mapping_method_fields form-group">
- <label for="mapping_bootstraps" class="col-xs-3 control-label">Bootstraps</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" for="mapping_bootstraps" class="col-xs-3 control-label">Bootstraps</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<input name="num_bootstrap" value="2000" type="text" class="form-control">
</div>
</div>
<div class="mapping_method_fields form-group">
- <label for="control_for" class="col-xs-3 control-label">Control&nbsp;for</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" for="control_for" class="col-xs-3 control-label">Control&nbsp;for</label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
{% if dataset.type == 'ProbeSet' and this_trait.locus_chr != "" %}
<input name="control_reaper" value="{{ nearest_marker }}" type="text" style="width: 160px;" class="form-control" />
{% else %}
@@ -162,8 +184,8 @@
<div class="mapping_method_fields form-group">
- <label style="text-align:left;" class="col-xs-3 control-label">Marker<br>Regression</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" class="col-xs-3 control-label">Marker<br>Regression</label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
<label class="radio-inline">
<input type="radio" name="manhattan_plot_reaper" value="True">
Yes
@@ -174,11 +196,12 @@
</label>
</div>
</div>
- <div class="form-group">
- <div style="padding-left:15px;" class="controls">
- <button id="interval_mapping_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Interval Mapping">
- <i class="icon-ok-circle icon-white"></i> Compute
- </button>
+ <div class="mapping_method_fields form-group">
+ <label class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6">
+ <button id="interval_mapping_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Interval Mapping">
+ Compute
+ </button>
</div>
</div>
<!--<div id="alert_placeholder"></div>-->
@@ -189,8 +212,8 @@
<div style="margin-top: 20px" class="form-horizontal">
{% if genofiles and genofiles|length>0 %}
<div class="mapping_method_fields form-group">
- <label for="genofiles" class="col-xs-3 control-label">Genotypes</label>
- <div style="margin-left: 20px;" class="col-xs-8 controls">
+ <label style="text-align:right;" for="genofiles" class="col-xs-3 control-label">Genotypes</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<select id="genofile_rqtl_geno" class="form-control">
{% for item in genofiles %}
<option value="{{item['location']}}:{{item['title']}}">{{item['title']}}</option>
@@ -200,17 +223,14 @@
</div>
{% endif %}
<div class="mapping_method_fields form-group">
- <label for="mapping_permutations" class="col-xs-3 control-label">Permutations</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
- <input name="num_perm_rqtl_geno" value="" type="text" class="form-control">
+ <label style="text-align:right;" for="mapping_permutations" class="col-xs-3 control-label">Permutations</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
+ <input name="num_perm_rqtl_geno" value="2000" type="text" class="form-control">
</div>
</div>
- <div id="permutations_alert" class="alert alert-error alert-warning" style="display:none;">
- Please be aware that permutations can take a very long time (~20 minutes for 500 permutations)
- </div>
<div class="mapping_method_fields form-group">
- <label for="control_for" class="col-xs-3 control-label">Control&nbsp;for</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
+ <label style="text-align:right;" for="control_for" class="col-xs-3 control-label">Control&nbsp;for</label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
{% if dataset.type == 'ProbeSet' and this_trait.locus_chr != "" %}
<input name="control_rqtl_geno" value="{{ nearest_marker }}" type="text" style="width: 160px;" class="form-control" />
{% else %}
@@ -228,8 +248,8 @@
</div>
<div class="mapping_method_fields form-group">
- <label for="mapmethod_rqtl_geno" style="text-align:left;" class="col-xs-3 control-label">Method</label>
- <div class="col-xs-4 controls">
+ <label style="text-align:right;" for="mapmethod_rqtl_geno" class="col-xs-3 control-label">Method</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<select name="mapmethod_rqtl_geno" class="form-control">
<option value="em">em</option>
<option value="imp">imp</option>
@@ -243,8 +263,8 @@
</div>
<div class="mapping_method_fields form-group">
- <label for="mapmodel_rqtl_geno" style="text-align:left;" class="col-xs-3 control-label">Model</label>
- <div class="col-xs-4 controls">
+ <label style="text-align:right;" for="mapmodel_rqtl_geno" class="col-xs-3 control-label">Model</label>
+ <div style="margin-left:20px;" class="col-xs-4 controls">
<select name="mapmodel_rqtl_geno" class="form-control">
<option value="normal">normal</option>
<!--<option value="binary">binary</option>
@@ -269,8 +289,8 @@
</div>
-->
<div class="mapping_method_fields form-group">
- <label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label>
- <div class="col-xs-12 controls">
+ <label style="text-align:right;" class="col-xs-3 control-label">Marker<br>Regression</label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
<label class="radio-inline">
<input type="radio" name="manhattan_plot_rqtl" value="True">
Yes
@@ -282,11 +302,12 @@
</div>
</div>
- <div class="form-group">
- <div style="padding-left:15px;" class="controls">
- <button id="rqtl_geno_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Marker Regression">
- <i class="icon-ok-circle icon-white"></i> Compute
- </button>
+ <div class="mapping_method_fields form-group">
+ <label class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6">
+ <button id="rqtl_geno_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Interval Mapping">
+ Compute
+ </button>
</div>
</div>
</div>
@@ -295,8 +316,8 @@
<div style="margin-top: 20px" class="form-horizontal">
{% if genofiles and genofiles|length>0 %}
<div class="mapping_method_fields form-group">
- <label for="genofiles" class="col-xs-3 control-label">Genotypes</label>
- <div style="margin-left: 20px;" class="col-xs-8 controls">
+ <label style="text-align:right;" class="col-xs-3 control-label">Genotypes</label>
+ <div style="margin-left: 20px;" class="col-xs-4 controls">
<select id="genofile_pylmm" class="form-control">
{% for item in genofiles %}
<option value="{{item['location']}}:{{item['title']}}">{{item['title']}}</option>
@@ -305,44 +326,12 @@
</div>
</div>
{% endif %}
-<!--
<div class="mapping_method_fields form-group">
- <label for="control_for" class="col-xs-3 control-label">Control&nbsp;for</label>
- <div style="margin-left: 20px;" class="col-xs-4 controls">
- {% if dataset.type == 'ProbeSet' and this_trait.locus_chr != "" %}
- <input name="control_pylmm" value="{{ nearest_marker }}" type="text" />
- {% else %}
- <input name="control_pylmm" value="" type="text" />
- {% endif %}
- <label class="radio-inline">
- <input type="radio" name="do_control_pylmm" value="true">
- Yes
- </label>
- <label class="radio-inline">
- <input type="radio" name="do_control_pylmm" value="false" checked="">
- No
- </label>
- </div>
- </div>
- <div class="mapping_method_fields form-group">
- <label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label>
- <div class="col-xs-12 controls">
- <label class="radio-inline">
- <input type="radio" name="manhattan_plot_pylmm" value="True">
- Yes
- </label>
- <label class="radio-inline">
- <input type="radio" name="manhattan_plot_pylmm" value="False" checked="">
- No
- </label>
- </div>
- </div>
--->
- <div class="form-group">
- <div style="padding-left:15px;" class="controls">
- <button id="pylmm_compute" class="btn submit_special btn-success" title="Compute Marker Regression">
- <i class="icon-ok-circle icon-white"></i> Compute
- </button>
+ <label class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6">
+ <button id="pylmm_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Interval Mapping">
+ Compute
+ </button>
</div>
</div>
</div>
@@ -354,8 +343,8 @@
<div style="padding-top: 10px;" class="form-horizontal">
{% if genofiles and genofiles|length>0 %}
<div class="mapping_method_fields form-group">
- <label for="genofiles" class="col-xs-3 control-label">Genotypes</label>
- <div style="margin-left: 20px;" class="col-xs-8 controls">
+ <label style="text-align:right;" class="col-xs-3 control-label">Genotypes</label>
+ <div style="margin-left: 20px;" class="col-xs-4 controls">
<select id="genofile_gemma" class="form-control">
{% for item in genofiles %}
<option value="{{item['location']}}:{{item['title']}}">{{item['title']}}</option>
@@ -365,29 +354,34 @@
</div>
{% endif %}
<div class="mapping_method_fields form-group">
- <label for="maf_gemma" class="col-xs-5 control-label">Minor allele threshold</label>
- <div style="margin-left: 20px;" class="col-xs-3 controls">
+ <label style="text-align:right;" class="col-xs-3 control-label">MAF</label>
+ <div style="margin-left: 20px;" class="col-xs-4 controls">
<input name="maf_gemma" value="0.01" type="text" class="form-control">
</div>
</div>
- </div>
-
- <div style="padding-top: 5px; padding-bottom: 5px; padding-left: 20px;" class="form-horizontal">
<div class="mapping_method_fields form-group">
- <button type="button" id="select_covariates" class="btn btn-default">
- Select Covariates
- </button>
- <button type="button" id="remove_covariates" class="btn btn-default">
- Remove Covariates
- </button>
+ <label style="text-align: right;" class="col-xs-3 control-label">Covariates</label>
+ <div style="margin-left:20px;" class="col-xs-7">
+ {% if g.user_session.user_ob and (g.user_session.user_ob.display_num_collections() == "") %}
+ No collections available. Please add traits to a collection to use them as covariates.
+ {% elif g.cookie_session.display_num_collections() == "" %}
+ No collections available. Please add traits to a collection to use them as covariates.
+ {% else %}
+ <div style="margin-bottom: 10px;" class="btn-group" role="group">
+ <button type="button" id="select_covariates" class="btn btn-default">Select</button>
+ <button type="button" id="remove_covariates" class="btn btn-default">Remove</button>
+ </div>
+ <textarea rows="3" cols="20" readonly placeholder="No covariates selected" style="overflow-y: scroll; resize: none;" class="selected_covariates"></textarea>
+ {% endif %}
+ </div>
</div>
- </div>
-
- <div class="form-group">
- <div class="col-xs-4 controls">
+ <div class="mapping_method_fields form-group">
+ <label class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6">
<button id="gemma_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Marker Regression">
Compute
</button>
+ </div>
</div>
</div>
</div>
@@ -395,16 +389,16 @@
<div class="tab-pane" id="plink">
<div style="padding: 20px" class="form-horizontal">
<div class="mapping_method_fields form-group">
- <label for="maf_plink" class="col-xs-3 control-label">Minor allele threshold</label>
- <div style="margin-left: 20px;" class="col-xs-3 controls">
+ <label style="text-align: right;" class="col-xs-3 control-label">MAF</label>
+ <div style="margin-left: 20px;" class="col-xs-4 controls">
<input name="maf_plink" value="0.01" type="text" class="form-control">
</div>
</div>
</div>
<div class="form-group">
- <label for="plink_compute" class="col-xs-1 control-label"></label>
- <div style="margin-left:20px;" class="col-xs-4 controls">
+ <label style="text-align: right;" class="col-xs-3 control-label"></label>
+ <div style="margin-left:20px;" class="col-xs-6 controls">
<button id="plink_compute" class="btn submit_special btn-success" data-url="/marker_regression" title="Compute Marker Regression">
Compute
</button>
@@ -416,25 +410,29 @@
</div>
</div>
</div>
- <div class="col-xs-6">
+ <div class="col-xs-5">
{% if dataset.group.mapping_id == "1" %}
<dl>
+ <dt>GEMMA</dt>
+ <dd>GEMMA is software implementing the Genome-wide Efficient Mixed Model Association algorithm for a standard linear mixed model for genome-wide association studies (GWAS).</dd>
<dt>Interval Mapping</dt>
<dd>Interval mapping is a process in which the statistical significance of a hypothetical QTL is evaluated at regular points across a chromosome, even in the absence of explicit genotype data at those points.</dd>
- <dt>pyLMM</dt>
- <dd>pyLMM is a fast and lightweight linear mixed-model (LMM) solver for use in genome-wide association studies (GWAS).</dd>
<dt>R/qtl</dt>
<dd>R/qtl is an extensible, interactive environment for mapping quantitative trait loci (QTL) in experimental crosses.</dd>
+ <dt>pyLMM</dt>
+ <dd>pyLMM is a fast and lightweight linear mixed-model (LMM) solver for use in genome-wide association studies (GWAS).</dd>
</dl>
{% else %}
<dl>
+ {% if mapping_method == "GEMMA" %}
<dt>GEMMA</dt>
<dd>
GEMMA is software implementing the Genome-wide Efficient Mixed Model Association algorithm for a standard linear mixed model for genome-wide association studies (GWAS).<br>
- Note: There currently exists an issue where GEMMA can't be run on traits from the same group simultaneously. If you receive an error, please wait a few minutes and try again.
</dd>
+ {% elif mapping_method == "PLINK" %}
<dt>PLINK</dt>
<dd>PLINK is a free, open-source whole genome association analysis toolset.</dd>
+ {% endif %}
</dl>
{% endif %}
</div>
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index c344ea27..ebca4807 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -55,7 +55,10 @@ logger = getLogger(__name__)
from base.data_set import create_datasets_list
import requests
-from utility.elasticsearch_tools import get_elasticsearch_connection, get_user_by_unique_column, save_user
+from utility.elasticsearch_tools import get_elasticsearch_connection, get_user_by_unique_column, get_item_by_unique_column, save_user, es_save_data
+
+from smtplib import SMTP
+from utility.tools import SMTP_CONNECT, SMTP_USERNAME, SMTP_PASSWORD
THREE_DAYS = 60 * 60 * 24 * 3
#THREE_DAYS = 45
@@ -386,6 +389,7 @@ class ForgotPasswordEmail(VerificationEmail):
"email_address": toaddr,
"timestamp": timestamp()
}
+ es = get_elasticsearch_connection()
es_save_data(es, self.key_prefix, "local", data, verification_code)
subject = self.subject
@@ -437,12 +441,12 @@ def verify_email():
@app.route("/n/password_reset", methods=['GET'])
def password_reset():
logger.debug("in password_reset request.url is:", request.url)
-
# We do this mainly just to assert that it's in proper form for displaying next page
# Really not necessary but doesn't hurt
# user_encode = DecodeUser(ForgotPasswordEmail.key_prefix).reencode_standalone()
verification_code = request.args.get('code')
hmac = request.args.get('hm')
+ es = get_elasticsearch_connection()
if verification_code:
code_details = get_item_by_unique_column(
es
@@ -466,7 +470,6 @@ def password_reset():
@app.route("/n/password_reset_step2", methods=('POST',))
def password_reset_step2():
- from utility.elasticsearch_tools import es
logger.debug("in password_reset request.url is:", request.url)
errors = []
@@ -626,13 +629,12 @@ class LoginUser(object):
logger.debug("in login params are:", params)
es = get_elasticsearch_connection()
if not params:
- from utility.tools import GITHUB_AUTH_URL, ORCID_AUTH_URL
- external_login = None
- if GITHUB_AUTH_URL or ORCID_AUTH_URL:
- external_login={
- "github": GITHUB_AUTH_URL,
- "orcid": ORCID_AUTH_URL
- }
+ from utility.tools import GITHUB_AUTH_URL, GITHUB_CLIENT_ID, ORCID_AUTH_URL, ORCID_CLIENT_ID
+ external_login = {}
+ if GITHUB_AUTH_URL and GITHUB_CLIENT_ID != 'UNKNOWN':
+ external_login["github"] = GITHUB_AUTH_URL
+ if ORCID_AUTH_URL and ORCID_CLIENT_ID != 'UNKNOWN':
+ external_login["orcid"] = ORCID_AUTH_URL
assert(es is not None)
return render_template(
"new_security/login_user.html"
@@ -749,6 +751,7 @@ def forgot_password():
def forgot_password_submit():
params = request.form
email_address = params['email_address']
+ es = get_elasticsearch_connection()
user_details = get_user_by_unique_column(es, "email_address", email_address)
if user_details:
ForgotPasswordEmail(user_details["email_address"])
@@ -915,15 +918,26 @@ app.jinja_env.globals.update(url_for_hmac=url_for_hmac,
# Redis.rpush("mail_queue", msg)
def send_email(toaddr, msg, fromaddr="no-reply@genenetwork.org"):
- from smtplib import SMTP
- from utility.tools import SMTP_CONNECT, SMTP_USERNAME, SMTP_PASSWORD
- server = SMTP(SMTP_CONNECT)
- server.starttls()
- server.login(SMTP_USERNAME, SMTP_PASSWORD)
- server.sendmail(fromaddr, toaddr, msg)
- server.quit()
-
-
+ """Send an E-mail through SMTP_CONNECT host. If SMTP_USERNAME is not
+ 'UNKNOWN' TLS is used
+
+ """
+ if SMTP_USERNAME == 'UNKNOWN':
+ logger.debug("SMTP: connecting with host "+SMTP_CONNECT)
+ server = SMTP(SMTP_CONNECT)
+ server.sendmail(fromaddr, toaddr, msg)
+ else:
+ logger.debug("SMTP: connecting TLS with host "+SMTP_CONNECT)
+ server = SMTP(SMTP_CONNECT)
+ server.starttls()
+ logger.debug("SMTP: login with user "+SMTP_USERNAME)
+ server.login(SMTP_USERNAME, SMTP_PASSWORD)
+ logger.debug("SMTP: "+fromaddr)
+ logger.debug("SMTP: "+toaddr)
+ logger.debug("SMTP: "+msg)
+ server.sendmail(fromaddr, toaddr, msg)
+ server.quit()
+ logger.info("Successfully sent email to "+toaddr)
class GroupsManager(object):
def __init__(self, kw):
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 4e81c29c..a65924d8 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -123,7 +123,7 @@ def handle_bad_request(e):
@app.route("/")
def index_page():
logger.info("Sending index_page")
- logger.error(request.url)
+ logger.info(request.url)
params = request.args
if 'import_collections' in params:
import_collections = params['import_collections']
@@ -141,7 +141,7 @@ def index_page():
def tmp_page(img_path):
logger.info("In tmp_page")
logger.info("img_path:", img_path)
- logger.error(request.url)
+ logger.info(request.url)
initial_start_vars = request.form
logger.info("initial_start_vars:", initial_start_vars)
imgfile = open(GENERATED_IMAGE_DIR + img_path, 'rb')
@@ -174,7 +174,7 @@ def twitter(filename):
@app.route("/search", methods=('GET',))
def search_page():
logger.info("in search_page")
- logger.error(request.url)
+ logger.info(request.url)
if 'info_database' in request.args:
logger.info("Going to sharing_info_page")
template_vars = sharing_info_page()
@@ -199,21 +199,22 @@ def search_page():
logger.info("request.args is", request.args)
the_search = search_results.SearchResultPage(request.args)
result = the_search.__dict__
+ valid_search = result['search_term_exists']
logger.debugf("result", result)
- if USE_REDIS:
+ if USE_REDIS and valid_search:
Redis.set(key, pickle.dumps(result, pickle.HIGHEST_PROTOCOL))
Redis.expire(key, 60*60)
- if result['search_term_exists']:
+ if valid_search:
return render_template("search_result_page.html", **result)
else:
return render_template("search_error.html")
@app.route("/gsearch", methods=('GET',))
def gsearchact():
- logger.error(request.url)
+ logger.info(request.url)
result = gsearch.GSearch(request.args).__dict__
type = request.args['type']
if type == "gene":
@@ -224,7 +225,7 @@ def gsearchact():
@app.route("/gsearch_updating", methods=('POST',))
def gsearch_updating():
logger.info("REQUEST ARGS:", request.values)
- logger.error(request.url)
+ logger.info(request.url)
result = update_search_results.GSearch(request.args).__dict__
return result['results']
# type = request.args['type']
@@ -235,31 +236,31 @@ def gsearch_updating():
@app.route("/docedit")
def docedit():
- logger.error(request.url)
+ logger.info(request.url)
doc = docs.Docs(request.args['entry'])
return render_template("docedit.html", **doc.__dict__)
@app.route('/generated/<filename>')
def generated_file(filename):
- logger.error(request.url)
+ logger.info(request.url)
return send_from_directory(GENERATED_IMAGE_DIR,filename)
@app.route("/help")
def help():
- logger.error(request.url)
+ logger.info(request.url)
doc = docs.Docs("help")
return render_template("docs.html", **doc.__dict__)
@app.route("/wgcna_setup", methods=('POST',))
def wcgna_setup():
logger.info("In wgcna, request.form is:", request.form) # We are going to get additional user input for the analysis
- logger.error(request.url)
+ logger.info(request.url)
return render_template("wgcna_setup.html", **request.form) # Display them using the template
@app.route("/wgcna_results", methods=('POST',))
def wcgna_results():
logger.info("In wgcna, request.form is:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
wgcna = wgcna_analysis.WGCNA() # Start R, load the package and pointers and create the analysis
wgcnaA = wgcna.run_analysis(request.form) # Start the analysis, a wgcnaA object should be a separate long running thread
result = wgcna.process_results(wgcnaA) # After the analysis is finished store the result
@@ -268,13 +269,13 @@ def wcgna_results():
@app.route("/ctl_setup", methods=('POST',))
def ctl_setup():
logger.info("In ctl, request.form is:", request.form) # We are going to get additional user input for the analysis
- logger.error(request.url)
+ logger.info(request.url)
return render_template("ctl_setup.html", **request.form) # Display them using the template
@app.route("/ctl_results", methods=('POST',))
def ctl_results():
logger.info("In ctl, request.form is:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
ctl = ctl_analysis.CTL() # Start R, load the package and pointers and create the analysis
ctlA = ctl.run_analysis(request.form) # Start the analysis, a ctlA object should be a separate long running thread
result = ctl.process_results(ctlA) # After the analysis is finished store the result
@@ -313,13 +314,13 @@ def environments():
@app.route("/submit_trait")
def submit_trait_form():
- logger.error(request.url)
+ logger.info(request.url)
species_and_groups = get_species_groups()
return render_template("submit_trait.html", **{'species_and_groups' : species_and_groups, 'gn_server_url' : GN_SERVER_URL, 'version' : GN_VERSION})
@app.route("/create_temp_trait", methods=('POST',))
def create_temp_trait():
- logger.error(request.url)
+ logger.info(request.url)
print("REQUEST.FORM:", request.form)
#template_vars = submit_trait.SubmitTrait(request.form)
@@ -332,7 +333,7 @@ def export_trait_excel():
"""Excel file consisting of the sample data from the trait data and analysis page"""
logger.info("In export_trait_excel")
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
sample_data = export_trait_data.export_sample_table(request.form)
logger.info("sample_data - type: %s -- size: %s" % (type(sample_data), len(sample_data)))
@@ -358,7 +359,7 @@ def export_trait_csv():
"""CSV file consisting of the sample data from the trait data and analysis page"""
logger.info("In export_trait_csv")
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
sample_data = export_trait_data.export_sample_table(request.form)
logger.info("sample_data - type: %s -- size: %s" % (type(sample_data), len(sample_data)))
@@ -379,7 +380,7 @@ def export_traits_csv():
"""CSV file consisting of the traits from the search result page"""
logger.info("In export_traits_csv")
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
csv_data = export_traits.export_search_results_csv(request.form)
return Response(csv_data,
@@ -389,7 +390,7 @@ def export_traits_csv():
@app.route('/export_perm_data', methods=('POST',))
def export_perm_data():
"""CSV file consisting of the permutation data for the mapping results"""
- logger.error(request.url)
+ logger.info(request.url)
num_perm = float(request.form['num_perm'])
perm_data = json.loads(request.form['perm_results'])
@@ -412,7 +413,7 @@ def export_perm_data():
@app.route("/show_temp_trait", methods=('POST',))
def show_temp_trait_page():
- logger.error(request.url)
+ logger.info(request.url)
template_vars = show_trait.ShowTrait(request.form)
#logger.info("js_data before dump:", template_vars.js_data)
template_vars.js_data = json.dumps(template_vars.js_data,
@@ -427,7 +428,7 @@ def show_temp_trait_page():
@app.route("/show_trait")
def show_trait_page():
- logger.error(request.url)
+ logger.info(request.url)
template_vars = show_trait.ShowTrait(request.args)
#logger.info("js_data before dump:", template_vars.js_data)
template_vars.js_data = json.dumps(template_vars.js_data,
@@ -443,7 +444,7 @@ def show_trait_page():
@app.route("/heatmap", methods=('POST',))
def heatmap_page():
logger.info("In heatmap, request.form is:", pf(request.form))
- logger.error(request.url)
+ logger.info(request.url)
start_vars = request.form
temp_uuid = uuid.uuid4()
@@ -493,7 +494,7 @@ def mapping_results_container_page():
@app.route("/loading", methods=('POST',))
def loading_page():
- logger.error(request.url)
+ logger.info(request.url)
initial_start_vars = request.form
logger.debug("Marker regression called with initial_start_vars:", initial_start_vars.items())
#temp_uuid = initial_start_vars['temp_uuid']
@@ -552,7 +553,7 @@ def loading_page():
def marker_regression_page():
initial_start_vars = request.form
logger.debug("Marker regression called with initial_start_vars:", initial_start_vars.items())
- logger.error(request.url)
+ logger.info(request.url)
temp_uuid = initial_start_vars['temp_uuid']
wanted = (
'trait_id',
@@ -582,7 +583,7 @@ def marker_regression_page():
'control_marker',
'control_marker_db',
'do_control',
- 'genofile',
+ 'genofile_string',
'pair_scan',
'startMb',
'endMb',
@@ -678,7 +679,7 @@ def marker_regression_page():
@app.route("/export_mapping_results", methods = ('POST',))
def export_mapping_results():
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
file_path = request.form.get("results_path")
results_csv = open(file_path, "r").read()
response = Response(results_csv,
@@ -691,7 +692,7 @@ def export_mapping_results():
@app.route("/export", methods = ('POST',))
def export():
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
svg_xml = request.form.get("data", "Invalid data")
filename = request.form.get("filename", "manhattan_plot_snp")
response = Response(svg_xml, mimetype="image/svg+xml")
@@ -702,7 +703,7 @@ def export():
def export_pdf():
import cairosvg
logger.info("request.form:", request.form)
- logger.error(request.url)
+ logger.info(request.url)
svg_xml = request.form.get("data", "Invalid data")
logger.info("svg_xml:", svg_xml)
filename = request.form.get("filename", "interval_map_pdf")
@@ -715,7 +716,7 @@ def export_pdf():
@app.route("/network_graph", methods=('POST',))
def network_graph_page():
logger.info("In network_graph, request.form is:", pf(request.form))
- logger.error(request.url)
+ logger.info(request.url)
start_vars = request.form
traits = [trait.strip() for trait in start_vars['trait_list'].split(',')]
if traits[0] != "":
@@ -731,7 +732,7 @@ def network_graph_page():
@app.route("/corr_compute", methods=('POST',))
def corr_compute_page():
logger.info("In corr_compute, request.form is:", pf(request.form))
- logger.error(request.url)
+ logger.info(request.url)
#fd = webqtlFormData.webqtlFormData(request.form)
template_vars = show_corr_results.CorrelationResults(request.form)
return render_template("correlation_page.html", **template_vars.__dict__)
@@ -739,11 +740,11 @@ def corr_compute_page():
@app.route("/corr_matrix", methods=('POST',))
def corr_matrix_page():
logger.info("In corr_matrix, request.form is:", pf(request.form))
- logger.error(request.url)
+ logger.info(request.url)
start_vars = request.form
traits = [trait.strip() for trait in start_vars['trait_list'].split(',')]
- if traits[0] != "":
+ if len(traits) > 1:
template_vars = show_corr_matrix.CorrelationMatrix(start_vars)
template_vars.js_data = json.dumps(template_vars.js_data,
default=json_default_handler,
@@ -755,7 +756,7 @@ def corr_matrix_page():
@app.route("/corr_scatter_plot")
def corr_scatter_plot_page():
- logger.error(request.url)
+ logger.info(request.url)
template_vars = corr_scatter_plot.CorrScatterPlot(request.args)
template_vars.js_data = json.dumps(template_vars.js_data,
default=json_default_handler,
@@ -764,7 +765,7 @@ def corr_scatter_plot_page():
@app.route("/submit_bnw", methods=('POST',))
def submit_bnw():
- logger.error(request.url)
+ logger.info(request.url)
template_vars = get_bnw_input(request.form)
return render_template("empty_collection.html", **{'tool':'Correlation Matrix'})
@@ -772,7 +773,7 @@ def submit_bnw():
def sharing_info_page():
"""Info page displayed when the user clicks the "Info" button next to the dataset selection"""
logger.info("In sharing_info_page")
- logger.error(request.url)
+ logger.info(request.url)
fd = webqtlFormData.webqtlFormData(request.args)
template_vars = SharingInfoPage.SharingInfoPage(fd)
return template_vars
@@ -780,7 +781,7 @@ def sharing_info_page():
# Take this out or secure it before putting into production
@app.route("/get_temp_data")
def get_temp_data():
- logger.error(request.url)
+ logger.info(request.url)
temp_uuid = request.args['key']
return flask.jsonify(temp_data.TempData(temp_uuid).get_all())