Merge pull request #3852 from minrk/isort

Use isort for import formatting
This commit is contained in:
Erik Sundell
2022-04-01 11:07:28 +02:00
committed by GitHub
85 changed files with 366 additions and 604 deletions

View File

@@ -18,10 +18,10 @@ repos:
- --py36-plus - --py36-plus
# Autoformat: Python code # Autoformat: Python code
- repo: https://github.com/asottile/reorder_python_imports - repo: https://github.com/pycqa/isort
rev: v3.0.1 rev: 5.10.1
hooks: hooks:
- id: reorder-python-imports - id: isort
# Autoformat: Python code # Autoformat: Python code
- repo: https://github.com/psf/black - repo: https://github.com/psf/black

View File

@@ -56,13 +56,15 @@ todo_include_todos = False
# Set the default role so we can use `foo` instead of ``foo`` # Set the default role so we can use `foo` instead of ``foo``
default_role = 'literal' default_role = 'literal'
# -- Config -------------------------------------------------------------
from jupyterhub.app import JupyterHub
from docutils import nodes
from sphinx.directives.other import SphinxDirective
from contextlib import redirect_stdout from contextlib import redirect_stdout
from io import StringIO from io import StringIO
from docutils import nodes
from sphinx.directives.other import SphinxDirective
# -- Config -------------------------------------------------------------
from jupyterhub.app import JupyterHub
# create a temp instance of JupyterHub just to get the output of the generate-config # create a temp instance of JupyterHub just to get the output of the generate-config
# and help --all commands. # and help --all commands.
jupyterhub_app = JupyterHub() jupyterhub_app = JupyterHub()

View File

@@ -7,9 +7,10 @@ to enable testing without administrative privileges.
c = get_config() # noqa c = get_config() # noqa
c.Application.log_level = 'DEBUG' c.Application.log_level = 'DEBUG'
from oauthenticator.azuread import AzureAdOAuthenticator
import os import os
from oauthenticator.azuread import AzureAdOAuthenticator
c.JupyterHub.authenticator_class = AzureAdOAuthenticator c.JupyterHub.authenticator_class = AzureAdOAuthenticator
c.AzureAdOAuthenticator.client_id = os.getenv("AAD_CLIENT_ID") c.AzureAdOAuthenticator.client_id = os.getenv("AAD_CLIENT_ID")

View File

@@ -5,12 +5,9 @@ from urllib.parse import urlparse
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.web import Application from tornado.web import Application, RequestHandler, authenticated
from tornado.web import authenticated
from tornado.web import RequestHandler
from jupyterhub.services.auth import HubOAuthCallbackHandler from jupyterhub.services.auth import HubOAuthCallbackHandler, HubOAuthenticated
from jupyterhub.services.auth import HubOAuthenticated
from jupyterhub.utils import url_path_join from jupyterhub.utils import url_path_join
SCOPE_PREFIX = "custom:grades" SCOPE_PREFIX = "custom:grades"

View File

@@ -5,13 +5,10 @@ so all URLs and requests necessary for OAuth with JupyterHub should be in one pl
""" """
import json import json
import os import os
from urllib.parse import urlencode from urllib.parse import urlencode, urlparse
from urllib.parse import urlparse
from tornado import log from tornado import log, web
from tornado import web from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPRequest
from tornado.httputil import url_concat from tornado.httputil import url_concat
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop

View File

@@ -16,7 +16,6 @@ import time
import requests import requests
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@@ -3,9 +3,7 @@ import datetime
import json import json
import os import os
from tornado import escape from tornado import escape, ioloop, web
from tornado import ioloop
from tornado import web
from jupyterhub.services.auth import HubAuthenticated from jupyterhub.services.auth import HubAuthenticated

View File

@@ -1,8 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any, Dict, List, Optional
from typing import Dict
from typing import List
from typing import Optional
from pydantic import BaseModel from pydantic import BaseModel

View File

@@ -1,9 +1,7 @@
import json import json
import os import os
from fastapi import HTTPException from fastapi import HTTPException, Security, status
from fastapi import Security
from fastapi import status
from fastapi.security import OAuth2AuthorizationCodeBearer from fastapi.security import OAuth2AuthorizationCodeBearer
from fastapi.security.api_key import APIKeyQuery from fastapi.security.api_key import APIKeyQuery

View File

@@ -1,14 +1,9 @@
import os import os
from fastapi import APIRouter from fastapi import APIRouter, Depends, Form, Request
from fastapi import Depends
from fastapi import Form
from fastapi import Request
from .client import get_client from .client import get_client
from .models import AuthorizationError from .models import AuthorizationError, HubApiError, User
from .models import HubApiError
from .models import User
from .security import get_current_user from .security import get_current_user
# APIRouter prefix cannot end in / # APIRouter prefix cannot end in /

View File

@@ -7,16 +7,10 @@ import os
import secrets import secrets
from functools import wraps from functools import wraps
from flask import Flask from flask import Flask, Response, make_response, redirect, request, session
from flask import make_response
from flask import redirect
from flask import request
from flask import Response
from flask import session
from jupyterhub.services.auth import HubOAuth from jupyterhub.services.auth import HubOAuth
prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/') prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/')
auth = HubOAuth(api_token=os.environ['JUPYTERHUB_API_TOKEN'], cache_max_age=60) auth = HubOAuth(api_token=os.environ['JUPYTERHUB_API_TOKEN'], cache_max_age=60)

View File

@@ -10,12 +10,9 @@ from urllib.parse import urlparse
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.web import Application from tornado.web import Application, RequestHandler, authenticated
from tornado.web import authenticated
from tornado.web import RequestHandler
from jupyterhub.services.auth import HubOAuthCallbackHandler from jupyterhub.services.auth import HubOAuthCallbackHandler, HubOAuthenticated
from jupyterhub.services.auth import HubOAuthenticated
from jupyterhub.utils import url_path_join from jupyterhub.utils import url_path_join

View File

@@ -10,9 +10,7 @@ from urllib.parse import urlparse
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.web import Application from tornado.web import Application, RequestHandler, authenticated
from tornado.web import authenticated
from tornado.web import RequestHandler
from jupyterhub.services.auth import HubAuthenticated from jupyterhub.services.auth import HubAuthenticated

View File

@@ -1,2 +1 @@
from ._version import __version__ from ._version import __version__, version_info
from ._version import version_info

View File

@@ -4,7 +4,7 @@
def get_data_files(): def get_data_files():
"""Walk up until we find share/jupyterhub""" """Walk up until we find share/jupyterhub"""
import sys import sys
from os.path import join, abspath, dirname, exists, split from os.path import abspath, dirname, exists, join, split
path = abspath(dirname(__file__)) path = abspath(dirname(__file__))
starting_points = [path] starting_points = [path]

View File

@@ -3,8 +3,7 @@ import sys
from logging.config import fileConfig from logging.config import fileConfig
from alembic import context from alembic import context
from sqlalchemy import engine_from_config from sqlalchemy import engine_from_config, pool
from sqlalchemy import pool
# this is the Alembic Config object, which provides # this is the Alembic Config object, which provides
# access to the values within the .ini file in use. # access to the values within the .ini file in use.
@@ -13,6 +12,7 @@ config = context.config
# This line sets up loggers basically. # This line sets up loggers basically.
if 'jupyterhub' in sys.modules: if 'jupyterhub' in sys.modules:
from traitlets.config import MultipleInstanceError from traitlets.config import MultipleInstanceError
from jupyterhub.app import JupyterHub from jupyterhub.app import JupyterHub
app = None app = None

View File

@@ -11,8 +11,8 @@ down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
def upgrade(): def upgrade():

View File

@@ -15,8 +15,8 @@ import logging
logger = logging.getLogger('alembic') logger = logging.getLogger('alembic')
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
tables = ('oauth_access_tokens', 'oauth_codes') tables = ('oauth_access_tokens', 'oauth_codes')

View File

@@ -22,8 +22,9 @@ import logging
logger = logging.getLogger('alembic') logger = logging.getLogger('alembic')
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
from jupyterhub.orm import JSONDict from jupyterhub.orm import JSONDict

View File

@@ -11,8 +11,9 @@ down_revision = '896818069c98'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
from jupyterhub.orm import JSONDict from jupyterhub.orm import JSONDict

View File

@@ -11,11 +11,11 @@ down_revision = '1cebaf56856c'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa
import logging import logging
import sqlalchemy as sa
from alembic import op
logger = logging.getLogger('alembic') logger = logging.getLogger('alembic')

View File

@@ -13,17 +13,12 @@ depends_on = None
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op from alembic import op
from sqlalchemy import Column from sqlalchemy import Column, ForeignKey, Integer, Table, Unicode
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Table
from sqlalchemy import Unicode
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
from jupyterhub import orm from jupyterhub import orm, roles
from jupyterhub import roles
def upgrade(): def upgrade():

View File

@@ -12,12 +12,11 @@ down_revision = '4dc2d5a8c53c'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
from jupyterhub import orm from jupyterhub import orm
naming_convention = orm.meta.naming_convention naming_convention = orm.meta.naming_convention

View File

@@ -11,8 +11,8 @@ down_revision = 'd68c98b66cd4'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
def upgrade(): def upgrade():

View File

@@ -12,11 +12,11 @@ branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa
from datetime import datetime from datetime import datetime
import sqlalchemy as sa
from alembic import op
def upgrade(): def upgrade():
op.add_column('users', sa.Column('created', sa.DateTime, nullable=True)) op.add_column('users', sa.Column('created', sa.DateTime, nullable=True))

View File

@@ -11,8 +11,8 @@ down_revision = 'eeb276e51423'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
def upgrade(): def upgrade():

View File

@@ -11,8 +11,8 @@ down_revision = '99a28a4418e1'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
def upgrade(): def upgrade():

View File

@@ -12,8 +12,9 @@ down_revision = '19c0846f6344'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op
from jupyterhub.orm import JSONDict from jupyterhub.orm import JSONDict

View File

@@ -1,9 +1,4 @@
from . import auth from . import auth, groups, hub, proxy, services, users
from . import groups
from . import hub
from . import proxy
from . import services
from . import users
from .base import * from .base import *
default_handlers = [] default_handlers = []

View File

@@ -4,22 +4,14 @@
import itertools import itertools
import json import json
from datetime import datetime from datetime import datetime
from urllib.parse import parse_qsl from urllib.parse import parse_qsl, quote, urlencode, urlparse, urlunparse
from urllib.parse import quote
from urllib.parse import urlencode
from urllib.parse import urlparse
from urllib.parse import urlunparse
from oauthlib import oauth2 from oauthlib import oauth2
from tornado import web from tornado import web
from .. import orm from .. import orm, roles, scopes
from .. import roles from ..utils import get_browser_protocol, token_authenticated
from .. import scopes from .base import APIHandler, BaseHandler
from ..utils import get_browser_protocol
from ..utils import token_authenticated
from .base import APIHandler
from .base import BaseHandler
class TokenAPIHandler(APIHandler): class TokenAPIHandler(APIHandler):

View File

@@ -4,10 +4,7 @@
import json import json
from functools import lru_cache from functools import lru_cache
from http.client import responses from http.client import responses
from urllib.parse import parse_qs from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
from urllib.parse import urlencode
from urllib.parse import urlparse
from urllib.parse import urlunparse
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from tornado import web from tornado import web
@@ -15,9 +12,7 @@ from tornado import web
from .. import orm from .. import orm
from ..handlers import BaseHandler from ..handlers import BaseHandler
from ..scopes import get_scopes_for from ..scopes import get_scopes_for
from ..utils import get_browser_protocol from ..utils import get_browser_protocol, isoformat, url_path_join
from ..utils import isoformat
from ..utils import url_path_join
PAGINATION_MEDIA_TYPE = "application/jupyterhub-pagination+json" PAGINATION_MEDIA_TYPE = "application/jupyterhub-pagination+json"

View File

@@ -6,8 +6,7 @@ import json
from tornado import web from tornado import web
from .. import orm from .. import orm
from ..scopes import needs_scope from ..scopes import Scope, needs_scope
from ..scopes import Scope
from .base import APIHandler from .base import APIHandler

View File

@@ -6,8 +6,7 @@ Currently GET-only, no actions can be taken to modify services.
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import json import json
from ..scopes import needs_scope from ..scopes import Scope, needs_scope
from ..scopes import Scope
from .base import APIHandler from .base import APIHandler

View File

@@ -3,26 +3,19 @@
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import asyncio import asyncio
import json import json
from datetime import datetime from datetime import datetime, timedelta, timezone
from datetime import timedelta
from datetime import timezone
from async_generator import aclosing from async_generator import aclosing
from dateutil.parser import parse as parse_date from dateutil.parser import parse as parse_date
from sqlalchemy import func from sqlalchemy import func, or_
from sqlalchemy import or_
from tornado import web from tornado import web
from tornado.iostream import StreamClosedError from tornado.iostream import StreamClosedError
from .. import orm from .. import orm, scopes
from .. import scopes
from ..roles import assign_default_roles from ..roles import assign_default_roles
from ..scopes import needs_scope from ..scopes import needs_scope
from ..user import User from ..user import User
from ..utils import isoformat from ..utils import isoformat, iterate_until, maybe_future, url_path_join
from ..utils import iterate_until
from ..utils import maybe_future
from ..utils import url_path_join
from .base import APIHandler from .base import APIHandler

View File

@@ -14,15 +14,11 @@ import socket
import sys import sys
import time import time
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from datetime import datetime from datetime import datetime, timedelta, timezone
from datetime import timedelta
from datetime import timezone
from getpass import getuser from getpass import getuser
from operator import itemgetter from operator import itemgetter
from textwrap import dedent from textwrap import dedent
from urllib.parse import unquote from urllib.parse import unquote, urlparse, urlunparse
from urllib.parse import urlparse
from urllib.parse import urlunparse
if sys.version_info[:2] < (3, 3): if sys.version_info[:2] < (3, 3):
raise ValueError("Python < 3.3 not supported: %s" % sys.version) raise ValueError("Python < 3.3 not supported: %s" % sys.version)
@@ -36,78 +32,72 @@ except AttributeError as e:
asyncio_all_tasks = asyncio.Task.all_tasks asyncio_all_tasks = asyncio.Task.all_tasks
asyncio_current_task = asyncio.Task.current_task asyncio_current_task = asyncio.Task.current_task
from dateutil.parser import parse as parse_date
from jinja2 import Environment, FileSystemLoader, PrefixLoader, ChoiceLoader
from sqlalchemy.exc import OperationalError, SQLAlchemyError
from tornado.httpclient import AsyncHTTPClient
import tornado.httpserver import tornado.httpserver
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.log import app_log, access_log, gen_log
import tornado.options import tornado.options
from dateutil.parser import parse as parse_date
from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader
from jupyter_telemetry.eventlog import EventLog
from sqlalchemy.exc import OperationalError, SQLAlchemyError
from tornado import gen, web from tornado import gen, web
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.log import access_log, app_log, gen_log
from traitlets import ( from traitlets import (
Unicode,
Integer,
Dict,
List,
Bool,
Any, Any,
Tuple, Bool,
Set,
Instance,
Bytes, Bytes,
Dict,
Float, Float,
Instance,
Integer,
List,
Set,
Tuple,
Unicode,
Union, Union,
observe,
default, default,
observe,
validate, validate,
) )
from traitlets.config import Application, Configurable, catch_config_error from traitlets.config import Application, Configurable, catch_config_error
from jupyter_telemetry.eventlog import EventLog
here = os.path.dirname(__file__) here = os.path.dirname(__file__)
import jupyterhub import jupyterhub
from . import handlers, apihandlers
from .handlers.static import CacheControlStaticFilesHandler, LogoHandler
from .services.service import Service
from . import crypto from . import apihandlers, crypto, dbutil, handlers, orm, roles, scopes
from . import dbutil
from . import orm
from . import roles
from . import scopes
from .user import UserDict
from .oauth.provider import make_provider
from ._data import DATA_FILES_PATH from ._data import DATA_FILES_PATH
from .log import CoroutineLogFormatter, log_request
from .proxy import Proxy, ConfigurableHTTPProxy
from .traitlets import URLPrefix, Command, EntryPointType, Callable
from .utils import (
AnyTimeoutError,
catch_db_error,
maybe_future,
url_path_join,
print_stacks,
print_ps_info,
make_ssl_context,
)
from .metrics import HUB_STARTUP_DURATION_SECONDS
from .metrics import INIT_SPAWNERS_DURATION_SECONDS
from .metrics import RUNNING_SERVERS
from .metrics import TOTAL_USERS
# classes for config # classes for config
from .auth import Authenticator, PAMAuthenticator from .auth import Authenticator, PAMAuthenticator
from .crypto import CryptKeeper from .crypto import CryptKeeper
from .spawner import Spawner, LocalProcessSpawner
from .objects import Hub, Server
# For faking stats # For faking stats
from .emptyclass import EmptyClass from .emptyclass import EmptyClass
from .handlers.static import CacheControlStaticFilesHandler, LogoHandler
from .log import CoroutineLogFormatter, log_request
from .metrics import (
HUB_STARTUP_DURATION_SECONDS,
INIT_SPAWNERS_DURATION_SECONDS,
RUNNING_SERVERS,
TOTAL_USERS,
)
from .oauth.provider import make_provider
from .objects import Hub, Server
from .proxy import ConfigurableHTTPProxy, Proxy
from .services.service import Service
from .spawner import LocalProcessSpawner, Spawner
from .traitlets import Callable, Command, EntryPointType, URLPrefix
from .user import UserDict
from .utils import (
AnyTimeoutError,
catch_db_error,
make_ssl_context,
maybe_future,
print_ps_info,
print_stacks,
url_path_join,
)
common_aliases = { common_aliases = {
'log-level': 'Application.log_level', 'log-level': 'Application.log_level',

View File

@@ -9,9 +9,7 @@ import warnings
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from functools import partial from functools import partial
from shutil import which from shutil import which
from subprocess import PIPE from subprocess import PIPE, STDOUT, Popen
from subprocess import Popen
from subprocess import STDOUT
try: try:
import pamela import pamela
@@ -20,13 +18,12 @@ except Exception as e:
_pamela_error = e _pamela_error = e
from tornado.concurrent import run_on_executor from tornado.concurrent import run_on_executor
from traitlets import Any, Bool, Dict, Integer, Set, Unicode, default, observe
from traitlets.config import LoggingConfigurable from traitlets.config import LoggingConfigurable
from traitlets import Bool, Integer, Set, Unicode, Dict, Any, default, observe
from .handlers.login import LoginHandler from .handlers.login import LoginHandler
from .utils import maybe_future, url_path_join
from .traitlets import Command from .traitlets import Command
from .utils import maybe_future, url_path_join
class Authenticator(LoggingConfigurable): class Authenticator(LoggingConfigurable):

View File

@@ -4,18 +4,12 @@ import os
from binascii import a2b_hex from binascii import a2b_hex
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from traitlets import Any from traitlets import Any, Integer, List, default, observe, validate
from traitlets import default from traitlets.config import Config, SingletonConfigurable
from traitlets import Integer
from traitlets import List
from traitlets import observe
from traitlets import validate
from traitlets.config import Config
from traitlets.config import SingletonConfigurable
try: try:
import cryptography import cryptography
from cryptography.fernet import Fernet, MultiFernet, InvalidToken from cryptography.fernet import Fernet, InvalidToken, MultiFernet
except ImportError: except ImportError:
cryptography = None cryptography = None

View File

@@ -1,7 +1,4 @@
from . import base from . import base, login, metrics, pages
from . import login
from . import metrics
from . import pages
from .base import * from .base import *
from .login import * from .login import *

View File

@@ -9,50 +9,43 @@ import random
import re import re
import time import time
import uuid import uuid
from datetime import datetime from datetime import datetime, timedelta
from datetime import timedelta
from http.client import responses from http.client import responses
from urllib.parse import parse_qs from urllib.parse import parse_qs, parse_qsl, urlencode, urlparse, urlunparse
from urllib.parse import parse_qsl
from urllib.parse import urlencode
from urllib.parse import urlparse
from urllib.parse import urlunparse
from jinja2 import TemplateNotFound from jinja2 import TemplateNotFound
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from tornado import gen from tornado import gen, web
from tornado import web from tornado.httputil import HTTPHeaders, url_concat
from tornado.httputil import HTTPHeaders
from tornado.httputil import url_concat
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.log import app_log from tornado.log import app_log
from tornado.web import addslash from tornado.web import RequestHandler, addslash
from tornado.web import RequestHandler
from .. import __version__ from .. import __version__, orm, roles, scopes
from .. import orm from ..metrics import (
from .. import roles PROXY_ADD_DURATION_SECONDS,
from .. import scopes PROXY_DELETE_DURATION_SECONDS,
from ..metrics import PROXY_ADD_DURATION_SECONDS RUNNING_SERVERS,
from ..metrics import PROXY_DELETE_DURATION_SECONDS SERVER_POLL_DURATION_SECONDS,
from ..metrics import ProxyDeleteStatus SERVER_SPAWN_DURATION_SECONDS,
from ..metrics import RUNNING_SERVERS SERVER_STOP_DURATION_SECONDS,
from ..metrics import SERVER_POLL_DURATION_SECONDS TOTAL_USERS,
from ..metrics import SERVER_SPAWN_DURATION_SECONDS ProxyDeleteStatus,
from ..metrics import SERVER_STOP_DURATION_SECONDS ServerPollStatus,
from ..metrics import ServerPollStatus ServerSpawnStatus,
from ..metrics import ServerSpawnStatus ServerStopStatus,
from ..metrics import ServerStopStatus )
from ..metrics import TOTAL_USERS
from ..objects import Server from ..objects import Server
from ..scopes import needs_scope from ..scopes import needs_scope
from ..spawner import LocalProcessSpawner from ..spawner import LocalProcessSpawner
from ..user import User from ..user import User
from ..utils import AnyTimeoutError from ..utils import (
from ..utils import get_accepted_mimetype AnyTimeoutError,
from ..utils import get_browser_protocol get_accepted_mimetype,
from ..utils import maybe_future get_browser_protocol,
from ..utils import url_path_join maybe_future,
url_path_join,
)
# pattern for the authentication token header # pattern for the authentication token header
auth_header_pat = re.compile(r'^(?:token|bearer)\s+([^\s]+)$', flags=re.IGNORECASE) auth_header_pat = re.compile(r'^(?:token|bearer)\s+([^\s]+)$', flags=re.IGNORECASE)

View File

@@ -1,7 +1,5 @@
"""Handlers for serving prometheus metrics""" """Handlers for serving prometheus metrics"""
from prometheus_client import CONTENT_TYPE_LATEST from prometheus_client import CONTENT_TYPE_LATEST, REGISTRY, generate_latest
from prometheus_client import generate_latest
from prometheus_client import REGISTRY
from ..utils import metrics_authentication from ..utils import metrics_authentication
from .base import BaseHandler from .base import BaseHandler

View File

@@ -12,11 +12,9 @@ from tornado import web
from tornado.httputil import url_concat from tornado.httputil import url_concat
from .. import __version__ from .. import __version__
from ..metrics import SERVER_POLL_DURATION_SECONDS from ..metrics import SERVER_POLL_DURATION_SECONDS, ServerPollStatus
from ..metrics import ServerPollStatus
from ..scopes import needs_scope from ..scopes import needs_scope
from ..utils import maybe_future from ..utils import maybe_future, url_path_join
from ..utils import url_path_join
from .base import BaseHandler from .base import BaseHandler

View File

@@ -6,13 +6,10 @@ import logging
import traceback import traceback
from functools import partial from functools import partial
from http.cookies import SimpleCookie from http.cookies import SimpleCookie
from urllib.parse import urlparse from urllib.parse import urlparse, urlunparse
from urllib.parse import urlunparse
from tornado.log import access_log from tornado.log import LogFormatter, access_log
from tornado.log import LogFormatter from tornado.web import HTTPError, StaticFileHandler
from tornado.web import HTTPError
from tornado.web import StaticFileHandler
from .handlers.pages import HealthCheckHandler from .handlers.pages import HealthCheckHandler
from .metrics import prometheus_log_method from .metrics import prometheus_log_method

View File

@@ -21,8 +21,7 @@ them manually here.
""" """
from enum import Enum from enum import Enum
from prometheus_client import Gauge from prometheus_client import Gauge, Histogram
from prometheus_client import Histogram
REQUEST_DURATION_SECONDS = Histogram( REQUEST_DURATION_SECONDS = Histogram(
'jupyterhub_request_duration_seconds', 'jupyterhub_request_duration_seconds',

View File

@@ -3,19 +3,14 @@
implements https://oauthlib.readthedocs.io/en/latest/oauth2/server.html implements https://oauthlib.readthedocs.io/en/latest/oauth2/server.html
""" """
from oauthlib import uri_validate from oauthlib import uri_validate
from oauthlib.oauth2 import RequestValidator from oauthlib.oauth2 import RequestValidator, WebApplicationServer
from oauthlib.oauth2 import WebApplicationServer from oauthlib.oauth2.rfc6749.grant_types import authorization_code, base
from oauthlib.oauth2.rfc6749.grant_types import authorization_code
from oauthlib.oauth2.rfc6749.grant_types import base
from tornado.log import app_log from tornado.log import app_log
from .. import orm from .. import orm
from ..roles import roles_to_scopes from ..roles import roles_to_scopes
from ..scopes import _check_scopes_exist from ..scopes import _check_scopes_exist, access_scopes, identify_scopes
from ..scopes import access_scopes from ..utils import compare_token, hash_token
from ..scopes import identify_scopes
from ..utils import compare_token
from ..utils import hash_token
# patch absolute-uri check # patch absolute-uri check
# because we want to allow relative uri oauth # because we want to allow relative uri oauth

View File

@@ -3,25 +3,20 @@
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import socket import socket
import warnings import warnings
from urllib.parse import urlparse from urllib.parse import urlparse, urlunparse
from urllib.parse import urlunparse
from traitlets import default from traitlets import HasTraits, Instance, Integer, Unicode, default, observe, validate
from traitlets import HasTraits
from traitlets import Instance
from traitlets import Integer
from traitlets import observe
from traitlets import Unicode
from traitlets import validate
from . import orm from . import orm
from .traitlets import URLPrefix from .traitlets import URLPrefix
from .utils import can_connect from .utils import (
from .utils import make_ssl_context can_connect,
from .utils import random_port make_ssl_context,
from .utils import url_path_join random_port,
from .utils import wait_for_http_server url_path_join,
from .utils import wait_for_server wait_for_http_server,
wait_for_server,
)
class Server(HasTraits): class Server(HasTraits):

View File

@@ -3,47 +3,44 @@
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import enum import enum
import json import json
from base64 import decodebytes from base64 import decodebytes, encodebytes
from base64 import encodebytes from datetime import datetime, timedelta
from datetime import datetime
from datetime import timedelta
import alembic.command import alembic.command
import alembic.config import alembic.config
from alembic.script import ScriptDirectory from alembic.script import ScriptDirectory
from sqlalchemy import Boolean from sqlalchemy import (
from sqlalchemy import Column Boolean,
from sqlalchemy import create_engine Column,
from sqlalchemy import DateTime DateTime,
from sqlalchemy import event ForeignKey,
from sqlalchemy import exc Integer,
from sqlalchemy import ForeignKey MetaData,
from sqlalchemy import inspect Table,
from sqlalchemy import Integer Unicode,
from sqlalchemy import MetaData create_engine,
from sqlalchemy import or_ event,
from sqlalchemy import select exc,
from sqlalchemy import Table inspect,
from sqlalchemy import Unicode or_,
select,
)
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref from sqlalchemy.orm import (
from sqlalchemy.orm import interfaces Session,
from sqlalchemy.orm import object_session backref,
from sqlalchemy.orm import relationship interfaces,
from sqlalchemy.orm import Session object_session,
from sqlalchemy.orm import sessionmaker relationship,
sessionmaker,
)
from sqlalchemy.pool import StaticPool from sqlalchemy.pool import StaticPool
from sqlalchemy.sql.expression import bindparam from sqlalchemy.sql.expression import bindparam
from sqlalchemy.types import LargeBinary from sqlalchemy.types import LargeBinary, Text, TypeDecorator
from sqlalchemy.types import Text
from sqlalchemy.types import TypeDecorator
from tornado.log import app_log from tornado.log import app_log
from .roles import roles_to_scopes from .roles import roles_to_scopes
from .utils import compare_token from .utils import compare_token, hash_token, new_token, random_port
from .utils import hash_token
from .utils import new_token
from .utils import random_port
# top-level variable for easier mocking in tests # top-level variable for easier mocking in tests
utcnow = datetime.utcnow utcnow = datetime.utcnow

View File

@@ -26,29 +26,18 @@ from subprocess import Popen
from urllib.parse import quote from urllib.parse import quote
from weakref import WeakKeyDictionary from weakref import WeakKeyDictionary
from tornado.httpclient import AsyncHTTPClient from tornado.httpclient import AsyncHTTPClient, HTTPError, HTTPRequest
from tornado.httpclient import HTTPError
from tornado.httpclient import HTTPRequest
from tornado.ioloop import PeriodicCallback from tornado.ioloop import PeriodicCallback
from traitlets import Any from traitlets import Any, Bool, Dict, Instance, Integer, Unicode, default, observe
from traitlets import Bool
from traitlets import default
from traitlets import Dict
from traitlets import Instance
from traitlets import Integer
from traitlets import observe
from traitlets import Unicode
from traitlets.config import LoggingConfigurable from traitlets.config import LoggingConfigurable
from . import utils
from .metrics import CHECK_ROUTES_DURATION_SECONDS
from .metrics import PROXY_POLL_DURATION_SECONDS
from .objects import Server
from .utils import AnyTimeoutError
from .utils import exponential_backoff
from .utils import url_path_join
from jupyterhub.traitlets import Command from jupyterhub.traitlets import Command
from . import utils
from .metrics import CHECK_ROUTES_DURATION_SECONDS, PROXY_POLL_DURATION_SECONDS
from .objects import Server
from .utils import AnyTimeoutError, exponential_backoff, url_path_join
def _one_at_a_time(method): def _one_at_a_time(method):
"""decorator to limit an async method to be called only once """decorator to limit an async method to be called only once

View File

@@ -7,8 +7,7 @@ from functools import wraps
from sqlalchemy import func from sqlalchemy import func
from tornado.log import app_log from tornado.log import app_log
from . import orm from . import orm, scopes
from . import scopes
def get_default_roles(): def get_default_roles():

View File

@@ -23,8 +23,7 @@ import sqlalchemy as sa
from tornado import web from tornado import web
from tornado.log import app_log from tornado.log import app_log
from . import orm from . import orm, roles
from . import roles
"""when modifying the scope definitions, make sure that `docs/source/rbac/generate-scope-table.py` is run """when modifying the scope definitions, make sure that `docs/source/rbac/generate-scope-table.py` is run
so that changes are reflected in the documentation and REST API description.""" so that changes are reflected in the documentation and REST API description."""

View File

@@ -40,21 +40,12 @@ from urllib.parse import urlencode
import requests import requests
from tornado.httputil import url_concat from tornado.httputil import url_concat
from tornado.log import app_log from tornado.log import app_log
from tornado.web import HTTPError from tornado.web import HTTPError, RequestHandler
from tornado.web import RequestHandler from traitlets import Dict, Instance, Integer, Set, Unicode, default, observe, validate
from traitlets import default
from traitlets import Dict
from traitlets import Instance
from traitlets import Integer
from traitlets import observe
from traitlets import Set
from traitlets import Unicode
from traitlets import validate
from traitlets.config import SingletonConfigurable from traitlets.config import SingletonConfigurable
from ..scopes import _intersect_expanded_scopes from ..scopes import _intersect_expanded_scopes
from ..utils import get_browser_protocol from ..utils import get_browser_protocol, url_path_join
from ..utils import url_path_join
def check_scopes(required_scopes, scopes): def check_scopes(required_scopes, scopes):

View File

@@ -45,21 +45,22 @@ import pipes
import shutil import shutil
from subprocess import Popen from subprocess import Popen
from traitlets import Any from traitlets import (
from traitlets import Bool Any,
from traitlets import default Bool,
from traitlets import Dict Dict,
from traitlets import HasTraits HasTraits,
from traitlets import Instance Instance,
from traitlets import List List,
from traitlets import Unicode Unicode,
from traitlets import validate default,
validate,
)
from traitlets.config import LoggingConfigurable from traitlets.config import LoggingConfigurable
from .. import orm from .. import orm
from ..objects import Server from ..objects import Server
from ..spawner import LocalProcessSpawner from ..spawner import LocalProcessSpawner, set_user_setuid
from ..spawner import set_user_setuid
from ..traitlets import Command from ..traitlets import Command
from ..utils import url_path_join from ..utils import url_path_join

View File

@@ -2,10 +2,8 @@
Contains default notebook-app subclass and mixins Contains default notebook-app subclass and mixins
""" """
from .app import main from .app import SingleUserNotebookApp, main
from .app import SingleUserNotebookApp from .mixins import HubAuthenticatedHandler, make_singleuser_app
from .mixins import HubAuthenticatedHandler
from .mixins import make_singleuser_app
# backward-compatibility # backward-compatibility
JupyterHubLoginHandler = SingleUserNotebookApp.login_handler_class JupyterHubLoginHandler = SingleUserNotebookApp.login_handler_class

View File

@@ -21,35 +21,29 @@ from importlib import import_module
from textwrap import dedent from textwrap import dedent
from urllib.parse import urlparse from urllib.parse import urlparse
from jinja2 import ChoiceLoader from jinja2 import ChoiceLoader, FunctionLoader
from jinja2 import FunctionLoader
from tornado import ioloop from tornado import ioloop
from tornado.httpclient import AsyncHTTPClient from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.httpclient import HTTPRequest
from tornado.web import RequestHandler from tornado.web import RequestHandler
from traitlets import Any from traitlets import (
from traitlets import Bool Any,
from traitlets import Bytes Bool,
from traitlets import CUnicode Bytes,
from traitlets import default CUnicode,
from traitlets import import_item Integer,
from traitlets import Integer TraitError,
from traitlets import observe Unicode,
from traitlets import TraitError default,
from traitlets import Unicode import_item,
from traitlets import validate observe,
validate,
)
from traitlets.config import Configurable from traitlets.config import Configurable
from .._version import __version__ from .._version import __version__, _check_version
from .._version import _check_version
from ..log import log_request from ..log import log_request
from ..services.auth import HubOAuth from ..services.auth import HubOAuth, HubOAuthCallbackHandler, HubOAuthenticated
from ..services.auth import HubOAuthCallbackHandler from ..utils import exponential_backoff, isoformat, make_ssl_context, url_path_join
from ..services.auth import HubOAuthenticated
from ..utils import exponential_backoff
from ..utils import isoformat
from ..utils import make_ssl_context
from ..utils import url_path_join
def _bool_env(key): def _bool_env(key):

View File

@@ -19,29 +19,31 @@ from urllib.parse import urlparse
from async_generator import aclosing from async_generator import aclosing
from sqlalchemy import inspect from sqlalchemy import inspect
from tornado.ioloop import PeriodicCallback from tornado.ioloop import PeriodicCallback
from traitlets import Any from traitlets import (
from traitlets import Bool Any,
from traitlets import default Bool,
from traitlets import Dict Dict,
from traitlets import Float Float,
from traitlets import Instance Instance,
from traitlets import Integer Integer,
from traitlets import List List,
from traitlets import observe Unicode,
from traitlets import Unicode Union,
from traitlets import Union default,
from traitlets import validate observe,
validate,
)
from traitlets.config import LoggingConfigurable from traitlets.config import LoggingConfigurable
from .objects import Server from .objects import Server
from .traitlets import ByteSpecification from .traitlets import ByteSpecification, Callable, Command
from .traitlets import Callable from .utils import (
from .traitlets import Command AnyTimeoutError,
from .utils import AnyTimeoutError exponential_backoff,
from .utils import exponential_backoff maybe_future,
from .utils import maybe_future random_port,
from .utils import random_port url_path_join,
from .utils import url_path_join )
if os.name == 'nt': if os.name == 'nt':
import psutil import psutil

View File

@@ -35,22 +35,17 @@ from getpass import getuser
from subprocess import TimeoutExpired from subprocess import TimeoutExpired
from unittest import mock from unittest import mock
from pytest import fixture from pytest import fixture, raises
from pytest import raises
from tornado import ioloop from tornado import ioloop
from tornado.httpclient import HTTPError from tornado.httpclient import HTTPError
from tornado.platform.asyncio import AsyncIOMainLoop from tornado.platform.asyncio import AsyncIOMainLoop
import jupyterhub.services.service import jupyterhub.services.service
from . import mocking
from .. import crypto from .. import crypto, orm, scopes
from .. import orm from ..roles import create_role, get_default_roles, mock_roles, update_roles
from .. import scopes
from ..roles import create_role
from ..roles import get_default_roles
from ..roles import mock_roles
from ..roles import update_roles
from ..utils import random_port from ..utils import random_port
from . import mocking
from .mocking import MockHub from .mocking import MockHub
from .test_services import mockservice_cmd from .test_services import mockservice_cmd
from .utils import add_user from .utils import add_user

View File

@@ -37,23 +37,15 @@ from urllib.parse import urlparse
from pamela import PAMError from pamela import PAMError
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from traitlets import Bool from traitlets import Bool, Dict, default
from traitlets import default
from traitlets import Dict
from .. import metrics from .. import metrics, orm, roles
from .. import orm
from .. import roles
from ..app import JupyterHub from ..app import JupyterHub
from ..auth import PAMAuthenticator from ..auth import PAMAuthenticator
from ..singleuser import SingleUserNotebookApp from ..singleuser import SingleUserNotebookApp
from ..spawner import SimpleLocalProcessSpawner from ..spawner import SimpleLocalProcessSpawner
from ..utils import random_port from ..utils import random_port, utcnow
from ..utils import utcnow from .utils import async_requests, public_host, public_url, ssl_setup
from .utils import async_requests
from .utils import public_host
from .utils import public_url
from .utils import ssl_setup
def mock_authenticate(username, password, service, encoding): def mock_authenticate(username, password, service, encoding):

View File

@@ -19,15 +19,14 @@ import sys
from urllib.parse import urlparse from urllib.parse import urlparse
import requests import requests
from tornado import httpserver from tornado import httpserver, ioloop, log, web
from tornado import ioloop
from tornado import log
from tornado import web
from tornado.httputil import url_concat from tornado.httputil import url_concat
from jupyterhub.services.auth import HubAuthenticated from jupyterhub.services.auth import (
from jupyterhub.services.auth import HubOAuthCallbackHandler HubAuthenticated,
from jupyterhub.services.auth import HubOAuthenticated HubOAuthCallbackHandler,
HubOAuthenticated,
)
from jupyterhub.utils import make_ssl_context from jupyterhub.utils import make_ssl_context
@@ -123,7 +122,7 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
from tornado.options import parse_command_line, options from tornado.options import options, parse_command_line
parse_command_line() parse_command_line()
options.logging = 'debug' options.logging = 'debug'

View File

@@ -16,10 +16,7 @@ import os
import sys import sys
from urllib.parse import urlparse from urllib.parse import urlparse
from tornado import httpserver from tornado import httpserver, ioloop, log, web
from tornado import ioloop
from tornado import log
from tornado import web
from tornado.options import options from tornado.options import options
from ..utils import make_ssl_context from ..utils import make_ssl_context

View File

@@ -4,32 +4,23 @@ import json
import re import re
import sys import sys
import uuid import uuid
from datetime import datetime from datetime import datetime, timedelta
from datetime import timedelta
from unittest import mock from unittest import mock
from urllib.parse import quote from urllib.parse import quote, urlparse, urlunparse
from urllib.parse import urlparse
from urllib.parse import urlunparse
from pytest import fixture from pytest import fixture, mark
from pytest import mark
from tornado.httputil import url_concat from tornado.httputil import url_concat
import jupyterhub import jupyterhub
from .. import orm from .. import orm
from ..apihandlers.base import PAGINATION_MEDIA_TYPE from ..apihandlers.base import PAGINATION_MEDIA_TYPE
from ..objects import Server from ..objects import Server
from ..utils import url_path_join as ujoin from ..utils import url_path_join as ujoin
from ..utils import utcnow from ..utils import utcnow
from .conftest import new_username from .conftest import new_username
from .mocking import public_host from .mocking import public_host, public_url
from .mocking import public_url from .utils import add_user, api_request, async_requests, auth_header, find_user
from .utils import add_user
from .utils import api_request
from .utils import async_requests
from .utils import auth_header
from .utils import find_user
# -------------------- # --------------------
# Authentication tests # Authentication tests

View File

@@ -6,11 +6,8 @@ import os
import re import re
import sys import sys
import time import time
from subprocess import check_output from subprocess import PIPE, Popen, check_output
from subprocess import PIPE from tempfile import NamedTemporaryFile, TemporaryDirectory
from subprocess import Popen
from tempfile import NamedTemporaryFile
from tempfile import TemporaryDirectory
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
@@ -18,8 +15,7 @@ import traitlets
from traitlets.config import Config from traitlets.config import Config
from .. import orm from .. import orm
from ..app import COOKIE_SECRET_BYTES from ..app import COOKIE_SECRET_BYTES, JupyterHub
from ..app import JupyterHub
from .mocking import MockHub from .mocking import MockHub
from .test_api import add_user from .test_api import add_user

View File

@@ -10,16 +10,10 @@ from requests import HTTPError
from traitlets import Any from traitlets import Any
from traitlets.config import Config from traitlets.config import Config
from .mocking import MockPAMAuthenticator from jupyterhub import auth, crypto, orm
from .mocking import MockStructGroup
from .mocking import MockStructPasswd from .mocking import MockPAMAuthenticator, MockStructGroup, MockStructPasswd
from .utils import add_user from .utils import add_user, async_requests, get_page, public_url
from .utils import async_requests
from .utils import get_page
from .utils import public_url
from jupyterhub import auth
from jupyterhub import crypto
from jupyterhub import orm
async def test_pam_auth(): async def test_pam_auth():

View File

@@ -9,13 +9,11 @@ authentication can expire in a number of ways:
""" """
from contextlib import contextmanager from contextlib import contextmanager
from unittest import mock from unittest import mock
from urllib.parse import parse_qs from urllib.parse import parse_qs, urlparse
from urllib.parse import urlparse
import pytest import pytest
from .utils import api_request from .utils import api_request, get_page
from .utils import get_page
async def refresh_expired(authenticator, user): async def refresh_expired(authenticator, user):

View File

@@ -1,13 +1,11 @@
import os import os
from binascii import b2a_base64 from binascii import b2a_base64, b2a_hex
from binascii import b2a_hex
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from .. import crypto from .. import crypto
from ..crypto import decrypt from ..crypto import decrypt, encrypt
from ..crypto import encrypt
keys = [('%i' % i).encode('ascii') * 32 for i in range(3)] keys = [('%i' % i).encode('ascii') * 32 for i in range(3)]
hex_keys = [b2a_hex(key).decode('ascii') for key in keys] hex_keys = [b2a_hex(key).decode('ascii') for key in keys]

View File

@@ -9,8 +9,7 @@ from pytest import raises
from traitlets.config import Config from traitlets.config import Config
from .. import orm from .. import orm
from ..app import NewToken from ..app import NewToken, UpgradeDB
from ..app import UpgradeDB
from ..scopes import _check_scopes_exist from ..scopes import _check_scopes_exist
here = os.path.abspath(os.path.dirname(__file__)) here = os.path.abspath(os.path.dirname(__file__))

View File

@@ -16,7 +16,6 @@ from traitlets.config import Config
from .mocking import MockHub from .mocking import MockHub
# To test new schemas, add them to the `valid_events` # To test new schemas, add them to the `valid_events`
# and `invalid_events` dictionary below. # and `invalid_events` dictionary below.

View File

@@ -4,8 +4,7 @@ import time
from unittest import mock from unittest import mock
import pytest import pytest
from requests.exceptions import ConnectionError from requests.exceptions import ConnectionError, SSLError
from requests.exceptions import SSLError
from ..utils import AnyTimeoutError from ..utils import AnyTimeoutError
from .test_api import add_user from .test_api import add_user

View File

@@ -3,11 +3,9 @@ from unittest import mock
import pytest import pytest
from .utils import api_request from jupyterhub import metrics, orm, roles
from .utils import get_page
from jupyterhub import metrics from .utils import api_request, get_page
from jupyterhub import orm
from jupyterhub import roles
async def test_total_users(app): async def test_total_users(app):

View File

@@ -2,22 +2,15 @@
import asyncio import asyncio
import json import json
from unittest import mock from unittest import mock
from urllib.parse import urlencode from urllib.parse import urlencode, urlparse
from urllib.parse import urlparse
import pytest import pytest
from tornado.httputil import url_concat from tornado.httputil import url_concat
from ..utils import url_path_join from ..utils import url_path_join
from .mocking import FormSpawner from .mocking import FormSpawner, public_url
from .mocking import public_url from .test_api import TIMESTAMP, add_user, api_request, fill_user, normalize_user
from .test_api import add_user from .utils import async_requests, get_page
from .test_api import api_request
from .test_api import fill_user
from .test_api import normalize_user
from .test_api import TIMESTAMP
from .utils import async_requests
from .utils import get_page
@pytest.fixture @pytest.fixture

View File

@@ -3,17 +3,13 @@
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import os import os
import socket import socket
from datetime import datetime from datetime import datetime, timedelta
from datetime import timedelta
from unittest import mock from unittest import mock
import pytest import pytest
from tornado import gen from tornado import gen
from .. import crypto from .. import crypto, objects, orm, roles
from .. import objects
from .. import orm
from .. import roles
from ..emptyclass import EmptyClass from ..emptyclass import EmptyClass
from ..user import User from ..user import User
from .mocking import MockSpawner from .mocking import MockSpawner

View File

@@ -2,31 +2,28 @@
import asyncio import asyncio
import sys import sys
from unittest import mock from unittest import mock
from urllib.parse import parse_qs from urllib.parse import parse_qs, urlencode, urlparse
from urllib.parse import urlencode
from urllib.parse import urlparse
import pytest import pytest
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from tornado.escape import url_escape from tornado.escape import url_escape
from tornado.httputil import url_concat from tornado.httputil import url_concat
from .. import orm from .. import orm, roles, scopes
from .. import roles
from .. import scopes
from ..auth import Authenticator from ..auth import Authenticator
from ..handlers import BaseHandler from ..handlers import BaseHandler
from ..utils import url_path_join from ..utils import url_path_join
from ..utils import url_path_join as ujoin from ..utils import url_path_join as ujoin
from .mocking import FalsyCallableFormSpawner from .mocking import FalsyCallableFormSpawner, FormSpawner
from .mocking import FormSpawner
from .test_api import next_event from .test_api import next_event
from .utils import api_request from .utils import (
from .utils import async_requests AsyncSession,
from .utils import AsyncSession api_request,
from .utils import get_page async_requests,
from .utils import public_host get_page,
from .utils import public_url public_host,
public_url,
)
async def test_root_no_auth(app): async def test_root_no_auth(app):

View File

@@ -3,8 +3,7 @@ import json
import os import os
from contextlib import contextmanager from contextlib import contextmanager
from subprocess import Popen from subprocess import Popen
from urllib.parse import quote from urllib.parse import quote, urlparse
from urllib.parse import urlparse
import pytest import pytest
from traitlets.config import Config from traitlets.config import Config
@@ -12,8 +11,7 @@ from traitlets.config import Config
from ..utils import url_path_join as ujoin from ..utils import url_path_join as ujoin
from ..utils import wait_for_http_server from ..utils import wait_for_http_server
from .mocking import MockHub from .mocking import MockHub
from .test_api import add_user from .test_api import add_user, api_request
from .test_api import api_request
from .utils import skip_if_ssl from .utils import skip_if_ssl

View File

@@ -8,14 +8,11 @@ import pytest
from pytest import mark from pytest import mark
from tornado.log import app_log from tornado.log import app_log
from .. import orm from .. import orm, roles
from .. import roles from ..scopes import get_scopes_for, scope_definitions
from ..scopes import get_scopes_for
from ..scopes import scope_definitions
from ..utils import utcnow from ..utils import utcnow
from .mocking import MockHub from .mocking import MockHub
from .utils import add_user from .utils import add_user, api_request
from .utils import api_request
@mark.role @mark.role

View File

@@ -7,22 +7,20 @@ from pytest import mark
from tornado import web from tornado import web
from tornado.httputil import HTTPServerRequest from tornado.httputil import HTTPServerRequest
from .. import orm from .. import orm, roles, scopes
from .. import roles
from .. import scopes
from ..handlers import BaseHandler from ..handlers import BaseHandler
from ..scopes import _check_scope_access from ..scopes import (
from ..scopes import _expand_self_scope Scope,
from ..scopes import _intersect_expanded_scopes _check_scope_access,
from ..scopes import expand_scopes _expand_self_scope,
from ..scopes import get_scopes_for _intersect_expanded_scopes,
from ..scopes import identify_scopes expand_scopes,
from ..scopes import needs_scope get_scopes_for,
from ..scopes import parse_scopes identify_scopes,
from ..scopes import Scope needs_scope,
from .utils import add_user parse_scopes,
from .utils import api_request )
from .utils import auth_header from .utils import add_user, api_request, auth_header
def get_handler_with_scopes(scopes): def get_handler_with_scopes(scopes):

View File

@@ -8,14 +8,15 @@ from async_generator import asynccontextmanager
from .. import orm from .. import orm
from ..roles import update_roles from ..roles import update_roles
from ..utils import exponential_backoff from ..utils import (
from ..utils import maybe_future exponential_backoff,
from ..utils import random_port maybe_future,
from ..utils import url_path_join random_port,
from ..utils import wait_for_http_server url_path_join,
wait_for_http_server,
)
from .mocking import public_url from .mocking import public_url
from .utils import async_requests from .utils import async_requests, skip_if_ssl
from .utils import skip_if_ssl
mockservice_path = os.path.dirname(os.path.abspath(__file__)) mockservice_path = os.path.dirname(os.path.abspath(__file__))
mockservice_py = os.path.join(mockservice_path, 'mockservice.py') mockservice_py = os.path.join(mockservice_path, 'mockservice.py')

View File

@@ -4,9 +4,7 @@ import os
import sys import sys
from binascii import hexlify from binascii import hexlify
from unittest import mock from unittest import mock
from urllib.parse import parse_qs from urllib.parse import parse_qs, quote, urlparse
from urllib.parse import quote
from urllib.parse import urlparse
import pytest import pytest
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
@@ -14,14 +12,11 @@ from pytest import raises
from tornado.httputil import url_concat from tornado.httputil import url_concat
from tornado.log import app_log from tornado.log import app_log
from .. import orm from .. import orm, roles, scopes
from .. import roles
from .. import scopes
from ..services.auth import _ExpiringDict from ..services.auth import _ExpiringDict
from ..utils import url_path_join from ..utils import url_path_join
from .mocking import public_url from .mocking import public_url
from .utils import async_requests from .utils import AsyncSession, async_requests
from .utils import AsyncSession
# mock for sending monotonic counter way into the future # mock for sending monotonic counter way into the future
monotonic_future = mock.patch('time.monotonic', lambda: sys.maxsize) monotonic_future = mock.patch('time.monotonic', lambda: sys.maxsize)

View File

@@ -2,20 +2,18 @@
import os import os
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
from subprocess import CalledProcessError from subprocess import CalledProcessError, check_output
from subprocess import check_output
from unittest import mock from unittest import mock
from urllib.parse import urlparse from urllib.parse import urlparse
import pytest import pytest
import jupyterhub import jupyterhub
from .. import orm from .. import orm
from ..utils import url_path_join from ..utils import url_path_join
from .mocking import public_url from .mocking import StubSingleUserSpawner, public_url
from .mocking import StubSingleUserSpawner from .utils import AsyncSession, async_requests
from .utils import async_requests
from .utils import AsyncSession
@contextmanager @contextmanager

View File

@@ -16,14 +16,10 @@ import pytest
from .. import orm from .. import orm
from .. import spawner as spawnermod from .. import spawner as spawnermod
from ..objects import Hub from ..objects import Hub, Server
from ..objects import Server from ..spawner import LocalProcessSpawner, Spawner
from ..spawner import LocalProcessSpawner
from ..spawner import Spawner
from ..user import User from ..user import User
from ..utils import AnyTimeoutError from ..utils import AnyTimeoutError, new_token, url_path_join
from ..utils import new_token
from ..utils import url_path_join
from .mocking import public_url from .mocking import public_url
from .test_api import add_user from .test_api import add_user
from .utils import async_requests from .utils import async_requests

View File

@@ -1,10 +1,7 @@
import pytest import pytest
from traitlets import HasTraits from traitlets import HasTraits, TraitError
from traitlets import TraitError
from jupyterhub.traitlets import ByteSpecification from jupyterhub.traitlets import ByteSpecification, Command, URLPrefix
from jupyterhub.traitlets import Command
from jupyterhub.traitlets import URLPrefix
def test_url_prefix(): def test_url_prefix():

View File

@@ -3,8 +3,7 @@ import logging
import pytest import pytest
from .._version import _check_version from .._version import _check_version, reset_globals
from .._version import reset_globals
def setup_function(function): def setup_function(function):

View File

@@ -7,11 +7,9 @@ import pytest
import requests import requests
from certipy import Certipy from certipy import Certipy
from jupyterhub import metrics from jupyterhub import metrics, orm
from jupyterhub import orm
from jupyterhub.objects import Server from jupyterhub.objects import Server
from jupyterhub.roles import assign_default_roles from jupyterhub.roles import assign_default_roles, update_roles
from jupyterhub.roles import update_roles
from jupyterhub.utils import url_path_join as ujoin from jupyterhub.utils import url_path_join as ujoin

View File

@@ -4,13 +4,7 @@ Traitlets that are used in JupyterHub
# Copyright (c) Jupyter Development Team. # Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import entrypoints import entrypoints
from traitlets import Integer from traitlets import Integer, List, TraitError, TraitType, Type, Undefined, Unicode
from traitlets import List
from traitlets import TraitError
from traitlets import TraitType
from traitlets import Type
from traitlets import Undefined
from traitlets import Unicode
class URLPrefix(Unicode): class URLPrefix(Unicode):

View File

@@ -3,34 +3,21 @@
import json import json
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from datetime import datetime from datetime import datetime, timedelta
from datetime import timedelta from urllib.parse import quote, urlparse
from urllib.parse import quote
from urllib.parse import urlparse
from sqlalchemy import inspect from sqlalchemy import inspect
from tornado import gen from tornado import gen, web
from tornado import web
from tornado.httputil import urlencode from tornado.httputil import urlencode
from tornado.log import app_log from tornado.log import app_log
from . import orm from . import orm
from ._version import __version__ from ._version import __version__, _check_version
from ._version import _check_version from .crypto import CryptKeeper, EncryptionUnavailable, InvalidToken, decrypt, encrypt
from .crypto import CryptKeeper from .metrics import RUNNING_SERVERS, TOTAL_USERS
from .crypto import decrypt
from .crypto import encrypt
from .crypto import EncryptionUnavailable
from .crypto import InvalidToken
from .metrics import RUNNING_SERVERS
from .metrics import TOTAL_USERS
from .objects import Server from .objects import Server
from .spawner import LocalProcessSpawner from .spawner import LocalProcessSpawner
from .utils import AnyTimeoutError from .utils import AnyTimeoutError, make_ssl_context, maybe_future, url_path_join
from .utils import make_ssl_context
from .utils import maybe_future
from .utils import url_path_join
# detailed messages about the most common failure-to-start errors, # detailed messages about the most common failure-to-start errors,
# which manifest timeouts during start # which manifest timeouts during start

View File

@@ -16,18 +16,14 @@ import threading
import uuid import uuid
import warnings import warnings
from binascii import b2a_hex from binascii import b2a_hex
from datetime import datetime from datetime import datetime, timezone
from datetime import timezone
from hmac import compare_digest from hmac import compare_digest
from operator import itemgetter from operator import itemgetter
from async_generator import aclosing from async_generator import aclosing
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from tornado import gen from tornado import gen, ioloop, web
from tornado import ioloop from tornado.httpclient import AsyncHTTPClient, HTTPError
from tornado import web
from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPError
from tornado.log import app_log from tornado.log import app_log
# For compatibility with python versions 3.6 or earlier. # For compatibility with python versions 3.6 or earlier.
@@ -477,6 +473,7 @@ def print_stacks(file=sys.stderr):
# no need to add them to startup # no need to add them to startup
import asyncio import asyncio
import traceback import traceback
from .log import coroutine_frames from .log import coroutine_frames
print("Active threads: %i" % threading.active_count(), file=file) print("Active threads: %i" % threading.active_count(), file=file)

View File

@@ -1,3 +1,6 @@
[tool.isort]
profile = "black"
[tool.black] [tool.black]
skip-string-normalization = true skip-string-normalization = true
target_version = [ target_version = [

View File

@@ -9,13 +9,11 @@ import shutil
import sys import sys
from subprocess import check_call from subprocess import check_call
from setuptools import Command from setuptools import Command, setup
from setuptools import setup
from setuptools.command.bdist_egg import bdist_egg from setuptools.command.bdist_egg import bdist_egg
from setuptools.command.build_py import build_py from setuptools.command.build_py import build_py
from setuptools.command.sdist import sdist from setuptools.command.sdist import sdist
v = sys.version_info v = sys.version_info
if v[:2] < (3, 6): if v[:2] < (3, 6):
error = "ERROR: JupyterHub requires Python version 3.6 or above." error = "ERROR: JupyterHub requires Python version 3.6 or above."