Browse Source

chore: blacken take 2 (#14360)

#skipsentry
josh 5 years ago
parent
commit
95767d455b
10 changed files with 346 additions and 377 deletions
  1. 8 6
      .pre-commit-config.yaml
  2. 1 1
      Makefile
  3. 115 144
      api-docs/generator.py
  4. 37 37
      api-docs/sentry.conf.py
  5. 78 78
      bin/yarn
  6. 6 7
      conftest.py
  7. 38 45
      examples/oauth2_consumer_webserver/app.py
  8. 5 0
      pyproject.toml
  9. 3 1
      setup.cfg
  10. 55 58
      setup.py

+ 8 - 6
.pre-commit-config.yaml

@@ -18,13 +18,15 @@ repos:
       name: flake8
       entry: flake8
       language: python
-      types: [python]
+      files: \.py$
       log_file: '.artifacts/flake8.pycodestyle.log'
-# -   repo: https://github.com/ambv/black
-#     rev: 18.6b2
-#     hooks:
-#     - id: black
-#       python_version: python3.6
+-   repo: https://github.com/ambv/black
+    rev: 19.3b0
+    hooks:
+    - id: black
+      python_version: python3
+      files: \.py$
+      exclude: (.eggs|.git|.venv|build|dist|south_migrations|node_modules)
 -   repo: git://github.com/pre-commit/pre-commit-hooks
     rev: v1.3.0
     hooks:

+ 1 - 1
Makefile

@@ -61,7 +61,7 @@ setup-git:
 	git config core.ignorecase false
 	cd .git/hooks && ln -sf ../../config/hooks/* ./
 	pip install "pre-commit>=1.10.1,<1.11.0"
-	pre-commit install
+	pre-commit install --install-hooks
 	@echo ""
 
 update-submodules:

+ 115 - 144
api-docs/generator.py

@@ -12,91 +12,92 @@ from subprocess import Popen, PIPE, check_output
 from six.moves.urllib.parse import urlparse
 
 HERE = os.path.abspath(os.path.dirname(__file__))
-SENTRY_CONFIG = os.environ['SENTRY_CONF'] = os.path.join(HERE, 'sentry.conf.py')
-os.environ['SENTRY_SKIP_BACKEND_VALIDATION'] = '1'
+SENTRY_CONFIG = os.environ["SENTRY_CONF"] = os.path.join(HERE, "sentry.conf.py")
+os.environ["SENTRY_SKIP_BACKEND_VALIDATION"] = "1"
 
 # No sentry or django imports before this point
 from sentry.runner import configure
+
 configure()
 from django.conf import settings
 
 # Fair game from here
 from django.core.management import call_command
 
-from sentry.utils.apidocs import (
-    Runner, MockUtils, iter_scenarios,
-    iter_endpoints, get_sections
-)
+from sentry.utils.apidocs import Runner, MockUtils, iter_scenarios, iter_endpoints, get_sections
 from sentry.web.helpers import render_to_string
 
 
-OUTPUT_PATH = os.path.join(HERE, 'cache')
-HOST = urlparse(settings.SENTRY_OPTIONS['system.url-prefix']).netloc
+OUTPUT_PATH = os.path.join(HERE, "cache")
+HOST = urlparse(settings.SENTRY_OPTIONS["system.url-prefix"]).netloc
 
 
 # We don't care about you, go away
-_logger = logging.getLogger('sentry.events')
+_logger = logging.getLogger("sentry.events")
 _logger.disabled = True
 
 
 def color_for_string(s):
-    colors = ('red', 'green', 'yellow', 'blue', 'cyan', 'magenta')
+    colors = ("red", "green", "yellow", "blue", "cyan", "magenta")
     return colors[zlib.crc32(s) % len(colors)]
 
 
 def report(category, message, fg=None):
     if fg is None:
         fg = color_for_string(category)
-    click.echo('[%s] %s: %s' % (
-        six.text_type(datetime.utcnow()).split('.')[0],
-        click.style(category, fg=fg),
-        message
-    ))
+    click.echo(
+        "[%s] %s: %s"
+        % (six.text_type(datetime.utcnow()).split(".")[0], click.style(category, fg=fg), message)
+    )
 
 
 def launch_redis():
-    report('redis', 'Launching redis server')
-    cl = Popen(['redis-server', '-'], stdin=PIPE, stdout=open(os.devnull, 'r+'))
-    cl.stdin.write('''
+    report("redis", "Launching redis server")
+    cl = Popen(["redis-server", "-"], stdin=PIPE, stdout=open(os.devnull, "r+"))
+    cl.stdin.write(
+        """
     port %(port)s
     databases %(databases)d
     save ""
-    ''' % {
-        'port': six.text_type(settings.SENTRY_APIDOCS_REDIS_PORT),
-        'databases': 4,
-    })
+    """
+        % {"port": six.text_type(settings.SENTRY_APIDOCS_REDIS_PORT), "databases": 4}
+    )
     cl.stdin.flush()
     cl.stdin.close()
     return cl
 
 
 def spawn_sentry():
-    report('sentry', 'Launching sentry server')
-    cl = Popen(['sentry', '--config=' + SENTRY_CONFIG, 'run', 'web',
-                '-w', '1', '--bind', '127.0.0.1:%s' % settings.SENTRY_APIDOCS_WEB_PORT])
+    report("sentry", "Launching sentry server")
+    cl = Popen(
+        [
+            "sentry",
+            "--config=" + SENTRY_CONFIG,
+            "run",
+            "web",
+            "-w",
+            "1",
+            "--bind",
+            "127.0.0.1:%s" % settings.SENTRY_APIDOCS_WEB_PORT,
+        ]
+    )
     return cl
 
 
 def init_db():
     drop_db()
-    report('db', 'Migrating database (this can take some time)')
-    call_command('syncdb', migrate=True, interactive=False,
-                 traceback=True, verbosity=0)
+    report("db", "Migrating database (this can take some time)")
+    call_command("syncdb", migrate=True, interactive=False, traceback=True, verbosity=0)
 
 
 def drop_db():
-    report('db', 'Dropping database')
-    config = settings.DATABASES['default']
-    check_output([
-        'dropdb', '-U', config['USER'], '-h', config['HOST'], config['NAME']
-    ])
-    check_output([
-        'createdb', '-U', config['USER'], '-h', config['HOST'], config['NAME']
-    ])
+    report("db", "Dropping database")
+    config = settings.DATABASES["default"]
+    check_output(["dropdb", "-U", config["USER"], "-h", config["HOST"], config["NAME"]])
+    check_output(["createdb", "-U", config["USER"], "-h", config["HOST"], config["NAME"]])
 
 
 class SentryBox(object):
-
     def __init__(self):
         self.redis = None
         self.sentry = None
@@ -110,25 +111,25 @@ class SentryBox(object):
 
     def __exit__(self, exc_type, exc_value, tb):
         if self.sentry is not None:
-            report('sentry', 'Shutting down sentry server')
+            report("sentry", "Shutting down sentry server")
             self.sentry.kill()
             self.sentry.wait()
         if self.redis is not None:
-            report('redis', 'Stopping redis server')
+            report("redis", "Stopping redis server")
             self.redis.kill()
             self.redis.wait()
 
 
 def run_scenario(vars, scenario_ident, func):
     runner = Runner(scenario_ident, func, **vars)
-    report('scenario', 'Running scenario "%s"' % scenario_ident)
+    report("scenario", 'Running scenario "%s"' % scenario_ident)
     func(runner)
     return runner.to_json()
 
 
 @click.command()
-@click.option('--output-path', type=click.Path())
-@click.option('--output-format', type=click.Choice(['json', 'markdown', 'both']), default='both')
+@click.option("--output-path", type=click.Path())
+@click.option("--output-format", type=click.Choice(["json", "markdown", "both"]), default="both")
 def cli(output_path, output_format):
     """API docs dummy generator."""
     global OUTPUT_PATH
@@ -136,151 +137,131 @@ def cli(output_path, output_format):
         OUTPUT_PATH = os.path.abspath(output_path)
     with SentryBox():
         utils = MockUtils()
-        report('org', 'Creating user and organization')
-        user = utils.create_user('john@interstellar.invalid')
-        org = utils.create_org('The Interstellar Jurisdiction',
-                               owner=user)
-        report('auth', 'Creating api token')
+        report("org", "Creating user and organization")
+        user = utils.create_user("john@interstellar.invalid")
+        org = utils.create_org("The Interstellar Jurisdiction", owner=user)
+        report("auth", "Creating api token")
         api_token = utils.create_api_token(user)
 
-        report('org', 'Creating team')
-        team = utils.create_team('Powerful Abolitionist',
-                                 org=org)
+        report("org", "Creating team")
+        team = utils.create_team("Powerful Abolitionist", org=org)
         utils.join_team(team, user)
 
         projects = []
-        for project_name in 'Pump Station', 'Prime Mover':
-            report('project', 'Creating project "%s"' % project_name)
+        for project_name in "Pump Station", "Prime Mover":
+            report("project", 'Creating project "%s"' % project_name)
             project = utils.create_project(project_name, teams=[team], org=org)
             release = utils.create_release(project=project, user=user)
-            report('event', 'Creating event for "%s"' % project_name)
-
-            event1 = utils.create_event(project=project, release=release,
-                                        platform='python')
-            event2 = utils.create_event(project=project, release=release,
-                                        platform='java')
-            projects.append({
-                'project': project,
-                'release': release,
-                'events': [event1, event2],
-            })
+            report("event", 'Creating event for "%s"' % project_name)
+
+            event1 = utils.create_event(project=project, release=release, platform="python")
+            event2 = utils.create_event(project=project, release=release, platform="java")
+            projects.append({"project": project, "release": release, "events": [event1, event2]})
 
         vars = {
-            'org': org,
-            'me': user,
-            'api_token': api_token,
-            'teams': [{
-                'team': team,
-                'projects': projects,
-            }],
+            "org": org,
+            "me": user,
+            "api_token": api_token,
+            "teams": [{"team": team, "projects": projects}],
         }
 
         scenario_map = {}
-        report('docs', 'Collecting scenarios')
+        report("docs", "Collecting scenarios")
         for scenario_ident, func in iter_scenarios():
             scenario = run_scenario(vars, scenario_ident, func)
             scenario_map[scenario_ident] = scenario
 
         section_mapping = {}
-        report('docs', 'Collecting endpoint documentation')
+        report("docs", "Collecting endpoint documentation")
         for endpoint in iter_endpoints():
-            report('endpoint', 'Collecting docs for "%s"' %
-                   endpoint['endpoint_name'])
+            report("endpoint", 'Collecting docs for "%s"' % endpoint["endpoint_name"])
 
-            section_mapping \
-                .setdefault(endpoint['section'], []) \
-                .append(endpoint)
+            section_mapping.setdefault(endpoint["section"], []).append(endpoint)
         sections = get_sections()
 
-        if output_format in ('json', 'both'):
+        if output_format in ("json", "both"):
             output_json(sections, scenario_map, section_mapping)
-        if output_format in ('markdown', 'both'):
+        if output_format in ("markdown", "both"):
             output_markdown(sections, scenario_map, section_mapping)
 
 
 def output_json(sections, scenarios, section_mapping):
-    report('docs', 'Generating JSON documents')
+    report("docs", "Generating JSON documents")
 
     for id, scenario in scenarios.items():
-        dump_json('scenarios/%s.json' % id, scenario)
+        dump_json("scenarios/%s.json" % id, scenario)
 
     section_listings = {}
     for section, title in sections.items():
         entries = {}
         for endpoint in section_mapping.get(section, []):
-            entries[endpoint['endpoint_name']] = endpoint['title']
-            dump_json('endpoints/%s.json' % endpoint['endpoint_name'],
-                      endpoint)
+            entries[endpoint["endpoint_name"]] = endpoint["title"]
+            dump_json("endpoints/%s.json" % endpoint["endpoint_name"], endpoint)
 
-        section_listings[section] = {
-            'title': title,
-            'entries': entries
-        }
-    dump_json('sections.json', {'sections': section_listings})
+        section_listings[section] = {"title": title, "entries": entries}
+    dump_json("sections.json", {"sections": section_listings})
 
 
 def output_markdown(sections, scenarios, section_mapping):
-    report('docs', 'Generating markdown documents')
+    report("docs", "Generating markdown documents")
     for section, title in sections.items():
         i = 0
         links = []
         for endpoint in section_mapping.get(section, []):
             i += 1
-            path = u"{}/{}.md".format(section, endpoint['endpoint_name'])
-            auth = ''
-            if len(endpoint['params'].get('auth', [])):
-                auth = endpoint['params']['auth'][0]['description']
+            path = u"{}/{}.md".format(section, endpoint["endpoint_name"])
+            auth = ""
+            if len(endpoint["params"].get("auth", [])):
+                auth = endpoint["params"]["auth"][0]["description"]
             payload = dict(
-                title=endpoint['title'],
+                title=endpoint["title"],
                 sidebar_order=i,
-                description='\n'.join(endpoint['text']).strip(),
-                warning=endpoint['warning'],
-                method=endpoint['method'],
-                api_path=endpoint['path'],
-                query_parameters=endpoint['params'].get('query'),
-                path_parameters=endpoint['params'].get('path'),
-                parameters=endpoint['params'].get('param'),
+                description="\n".join(endpoint["text"]).strip(),
+                warning=endpoint["warning"],
+                method=endpoint["method"],
+                api_path=endpoint["path"],
+                query_parameters=endpoint["params"].get("query"),
+                path_parameters=endpoint["params"].get("path"),
+                parameters=endpoint["params"].get("param"),
                 authentication=auth,
                 example_request=format_request(endpoint, scenarios),
-                example_response=format_response(endpoint, scenarios)
+                example_response=format_response(endpoint, scenarios),
             )
             dump_markdown(path, payload)
 
-            links.append({'title': endpoint['title'], 'path': path})
+            links.append({"title": endpoint["title"], "path": path})
         dump_index_markdown(section, title, links)
 
 
 def dump_json(path, data):
-    path = os.path.join(OUTPUT_PATH, 'json', path)
+    path = os.path.join(OUTPUT_PATH, "json", path)
     try:
         os.makedirs(os.path.dirname(path))
     except OSError:
         pass
-    with open(path, 'w') as f:
+    with open(path, "w") as f:
         for line in json.dumps(data, indent=2, sort_keys=True).splitlines():
-            f.write(line.rstrip() + '\n')
+            f.write(line.rstrip() + "\n")
 
 
 def dump_index_markdown(section, title, links):
-    path = os.path.join(OUTPUT_PATH, 'markdown', section, 'index.md')
+    path = os.path.join(OUTPUT_PATH, "markdown", section, "index.md")
     try:
         os.makedirs(os.path.dirname(path))
     except OSError:
         pass
-    with open(path, 'w') as f:
-        contents = render_to_string(
-            'sentry/apidocs/index.md',
-            dict(title=title, links=links))
+    with open(path, "w") as f:
+        contents = render_to_string("sentry/apidocs/index.md", dict(title=title, links=links))
         f.write(contents)
 
 
 def dump_markdown(path, data):
-    path = os.path.join(OUTPUT_PATH, 'markdown', path)
+    path = os.path.join(OUTPUT_PATH, "markdown", path)
     try:
         os.makedirs(os.path.dirname(path))
     except OSError:
         pass
-    with open(path, 'w') as f:
+    with open(path, "w") as f:
         template = u"""---
 # This file is automatically generated from the API using `sentry/api-docs/generator.py.`
 # Do not manually edit this file.
@@ -292,11 +273,11 @@ def dump_markdown(path, data):
 
 
 def find_first_scenario(endpoint, scenario_map):
-    for scene in endpoint['scenarios']:
+    for scene in endpoint["scenarios"]:
         if scene not in scenario_map:
             continue
         try:
-            return scenario_map[scene]['requests'][0]
+            return scenario_map[scene]["requests"][0]
         except IndexError:
             return None
     return None
@@ -305,47 +286,37 @@ def find_first_scenario(endpoint, scenario_map):
 def format_request(endpoint, scenario_map):
     scene = find_first_scenario(endpoint, scenario_map)
     if not scene:
-        return ''
-    request = scene['request']
+        return ""
+    request = scene["request"]
     lines = [
-        u"{} {} HTTP/1.1".format(request['method'], request['path']),
-        'Host: sentry.io',
-        'Authorization: Bearer <token>',
+        u"{} {} HTTP/1.1".format(request["method"], request["path"]),
+        "Host: sentry.io",
+        "Authorization: Bearer <token>",
     ]
-    lines.extend(format_headers(request['headers']))
-    if request['data']:
-        lines.append('')
-        lines.append(json.dumps(request['data'],
-                                sort_keys=True,
-                                indent=2))
+    lines.extend(format_headers(request["headers"]))
+    if request["data"]:
+        lines.append("")
+        lines.append(json.dumps(request["data"], sort_keys=True, indent=2))
     return "\n".join(lines)
 
 
 def format_response(endpoint, scenario_map):
     scene = find_first_scenario(endpoint, scenario_map)
     if not scene:
-        return ''
-    response = scene['response']
-    lines = [
-        u"HTTP/1.1 {} {}".format(response['status'], response['reason']),
-    ]
-    lines.extend(format_headers(response['headers']))
-    if response['data']:
-        lines.append('')
-        lines.append(json.dumps(response['data'],
-                                sort_keys=True,
-                                indent=2))
+        return ""
+    response = scene["response"]
+    lines = [u"HTTP/1.1 {} {}".format(response["status"], response["reason"])]
+    lines.extend(format_headers(response["headers"]))
+    if response["data"]:
+        lines.append("")
+        lines.append(json.dumps(response["data"], sort_keys=True, indent=2))
     return "\n".join(lines)
 
 
 def format_headers(headers):
     """Format headers into a list."""
-    return [
-        u'{}: {}'.format(key, value)
-        for key, value
-        in headers.items()
-    ]
+    return [u"{}: {}".format(key, value) for key, value in headers.items()]
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     cli()

+ 37 - 37
api-docs/sentry.conf.py

@@ -8,7 +8,7 @@ import getpass
 SENTRY_APIDOCS_REDIS_PORT = 12355
 SENTRY_APIDOCS_WEB_PORT = 12356
 
-SENTRY_URL_PREFIX = 'https://sentry.io'
+SENTRY_URL_PREFIX = "https://sentry.io"
 
 # Unsupported here
 SENTRY_SINGLE_ORGANIZATION = False
@@ -18,55 +18,55 @@ DEBUG = True
 CONF_ROOT = os.path.dirname(__file__)
 
 DATABASES = {
-    'default': {
-        'ENGINE': 'sentry.db.postgres',
-        'NAME': 'sentry_api_docs',
-        'USER': 'postgres',
-        'PASSWORD': '',
-        'HOST': '127.0.0.1',
+    "default": {
+        "ENGINE": "sentry.db.postgres",
+        "NAME": "sentry_api_docs",
+        "USER": "postgres",
+        "PASSWORD": "",
+        "HOST": "127.0.0.1",
     }
 }
 SENTRY_USE_BIG_INTS = True
 
-SENTRY_CACHE = 'sentry.cache.redis.RedisCache'
+SENTRY_CACHE = "sentry.cache.redis.RedisCache"
 
 CELERY_ALWAYS_EAGER = True
-BROKER_URL = 'redis://localhost:%s' % SENTRY_APIDOCS_REDIS_PORT
+BROKER_URL = "redis://localhost:%s" % SENTRY_APIDOCS_REDIS_PORT
 
-SENTRY_RATELIMITER = 'sentry.ratelimits.redis.RedisRateLimiter'
-SENTRY_BUFFER = 'sentry.buffer.redis.RedisBuffer'
-SENTRY_QUOTAS = 'sentry.quotas.redis.RedisQuota'
-SENTRY_TSDB = 'sentry.tsdb.redis.RedisTSDB'
+SENTRY_RATELIMITER = "sentry.ratelimits.redis.RedisRateLimiter"
+SENTRY_BUFFER = "sentry.buffer.redis.RedisBuffer"
+SENTRY_QUOTAS = "sentry.quotas.redis.RedisQuota"
+SENTRY_TSDB = "sentry.tsdb.redis.RedisTSDB"
 
-LOGIN_REDIRECT_URL = SENTRY_URL_PREFIX + '/'
+LOGIN_REDIRECT_URL = SENTRY_URL_PREFIX + "/"
 
-SENTRY_WEB_HOST = '127.0.0.1'
+SENTRY_WEB_HOST = "127.0.0.1"
 SENTRY_WEB_PORT = SENTRY_APIDOCS_WEB_PORT
 SENTRY_WEB_OPTIONS = {
-    'workers': 2,
-    'limit_request_line': 0,
-    'secure_scheme_headers': {'X-FORWARDED-PROTO': 'https'},
+    "workers": 2,
+    "limit_request_line": 0,
+    "secure_scheme_headers": {"X-FORWARDED-PROTO": "https"},
 }
 
-SENTRY_OPTIONS.update({
-    'redis.clusters': {
-        'default': {
-            'hosts': {i: {'port': SENTRY_APIDOCS_REDIS_PORT} for i in range(0, 4)},
+SENTRY_OPTIONS.update(
+    {
+        "redis.clusters": {
+            "default": {"hosts": {i: {"port": SENTRY_APIDOCS_REDIS_PORT} for i in range(0, 4)}}
         },
-    },
-    'system.secret-key': 'super secret secret key',
-    'system.admin-email': 'admin@sentry.io',
-    'system.url-prefix': SENTRY_URL_PREFIX,
-    'mail.backend': 'django.core.mail.backends.smtp.EmailBackend',
-    'mail.host': 'localhost',
-    'mail.password': '',
-    'mail.username': '',
-    'mail.port': 25,
-    'mail.use-tls': False,
-    'mail.from': 'sentry@sentry.io',
-    'filestore.backend': 'filesystem',
-    'filestore.options': {'location': '/tmp/sentry-files'},
-})
+        "system.secret-key": "super secret secret key",
+        "system.admin-email": "admin@sentry.io",
+        "system.url-prefix": SENTRY_URL_PREFIX,
+        "mail.backend": "django.core.mail.backends.smtp.EmailBackend",
+        "mail.host": "localhost",
+        "mail.password": "",
+        "mail.username": "",
+        "mail.port": 25,
+        "mail.use-tls": False,
+        "mail.from": "sentry@sentry.io",
+        "filestore.backend": "filesystem",
+        "filestore.options": {"location": "/tmp/sentry-files"},
+    }
+)
 
 # Enable feature flags so sample responses generate.
-SENTRY_FEATURES['projects:servicehooks'] = True
+SENTRY_FEATURES["projects:servicehooks"] = True

+ 78 - 78
bin/yarn

@@ -4328,7 +4328,7 @@ function coerce(version) {
   if (match == null)
     return null;
 
-  return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); 
+  return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0'));
 }
 
 
@@ -37385,7 +37385,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
 // This will be bundled directly in the .js file for production builds
 var _require = __webpack_require__(194); /**
                                                * Determines the current version of Yarn itself.
-                                               * 
+                                               *
                                                */
 
 const version = _require.version,
@@ -39978,7 +39978,7 @@ ECFieldElementFp.prototype.modReduce = function(x)
             {
                 u = u.multiply(this.getR());
             }
-            x = u.add(v); 
+            x = u.add(v);
         }
         while (x.compareTo(q) >= 0)
         {
@@ -40510,18 +40510,18 @@ function mkdirP (p, opts, f, made) {
     else if (!opts || typeof opts !== 'object') {
         opts = { mode: opts };
     }
-    
+
     var mode = opts.mode;
     var xfs = opts.fs || fs;
-    
+
     if (mode === undefined) {
         mode = _0777 & (~process.umask());
     }
     if (!made) made = null;
-    
+
     var cb = f || function () {};
     p = path.resolve(p);
-    
+
     xfs.mkdir(p, mode, function (er) {
         if (!er) {
             made = made || p;
@@ -40554,10 +40554,10 @@ mkdirP.sync = function sync (p, opts, made) {
     if (!opts || typeof opts !== 'object') {
         opts = { mode: opts };
     }
-    
+
     var mode = opts.mode;
     var xfs = opts.fs || fs;
-    
+
     if (mode === undefined) {
         mode = _0777 & (~process.umask());
     }
@@ -81012,11 +81012,11 @@ exports.ECKey = function(curve, key, isPublic)
 //      var y = key.slice(bytes+1);
 //      this.P = new ECPointFp(curve,
 //        curve.fromBigInteger(new BigInteger(x.toString("hex"), 16)),
-//        curve.fromBigInteger(new BigInteger(y.toString("hex"), 16)));      
+//        curve.fromBigInteger(new BigInteger(y.toString("hex"), 16)));
       this.P = curve.decodePointHex(key.toString("hex"));
     }else{
       if(key.length != bytes) return false;
-      priv = new BigInteger(key.toString("hex"), 16);      
+      priv = new BigInteger(key.toString("hex"), 16);
     }
   }else{
     var n1 = n.subtract(BigInteger.ONE);
@@ -81038,7 +81038,7 @@ exports.ECKey = function(curve, key, isPublic)
       if(!key || !key.P) return false;
       var S = key.P.multiply(priv);
       return Buffer.from(unstupid(S.getX().toBigInteger().toString(16),bytes*2),"hex");
-   }     
+   }
   }
 }
 
@@ -88481,7 +88481,7 @@ inherits(DestroyableTransform, Transform)
 DestroyableTransform.prototype.destroy = function(err) {
   if (this._destroyed) return
   this._destroyed = true
-  
+
   var self = this
   process.nextTick(function() {
     if (err)
@@ -88602,7 +88602,7 @@ function bytesToUuid(buf, offset) {
   var i = offset || 0;
   var bth = byteToHex;
   // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
-  return ([bth[buf[i++]], bth[buf[i++]], 
+  return ([bth[buf[i++]], bth[buf[i++]],
 	bth[buf[i++]], bth[buf[i++]], '-',
 	bth[buf[i++]], bth[buf[i++]], '-',
 	bth[buf[i++]], bth[buf[i++]], '-',
@@ -88954,7 +88954,7 @@ threshold'), { code: 'ECOMPROMISED' }));
     // on process exit
 
     // We first check that `lock.updateTimeout.unref` exists because some users
-    // may be using this module outside of NodeJS (e.g., in an electron app), 
+    // may be using this module outside of NodeJS (e.g., in an electron app),
     // and in those cases `setTimeout` return an integer.
     if (lock.updateTimeout.unref) {
         lock.updateTimeout.unref();
@@ -94800,7 +94800,7 @@ var crypto = __webpack_require__(12)
  * Valid keys.
  */
 
-var keys = 
+var keys =
   [ 'acl'
   , 'location'
   , 'logging'
@@ -94839,7 +94839,7 @@ module.exports.authorization = authorization
  * @param {Object} options
  * @return {String}
  * @api private
- */ 
+ */
 
 function hmacSha1 (options) {
   return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64')
@@ -94848,8 +94848,8 @@ function hmacSha1 (options) {
 module.exports.hmacSha1 = hmacSha1
 
 /**
- * Create a base64 sha1 HMAC for `options`. 
- * 
+ * Create a base64 sha1 HMAC for `options`.
+ *
  * @param {Object} options
  * @return {String}
  * @api private
@@ -94862,10 +94862,10 @@ function sign (options) {
 module.exports.sign = sign
 
 /**
- * Create a base64 sha1 HMAC for `options`. 
+ * Create a base64 sha1 HMAC for `options`.
  *
  * Specifically to be used with S3 presigned URLs
- * 
+ *
  * @param {Object} options
  * @return {String}
  * @api private
@@ -94881,7 +94881,7 @@ module.exports.signQuery= signQuery
  * Return a string for sign() with the given `options`.
  *
  * Spec:
- * 
+ *
  *    <verb>\n
  *    <md5>\n
  *    <content-type>\n
@@ -94897,7 +94897,7 @@ module.exports.signQuery= signQuery
 function stringToSign (options) {
   var headers = options.amazonHeaders || ''
   if (headers) headers += '\n'
-  var r = 
+  var r =
     [ options.verb
     , options.md5
     , options.contentType
@@ -94913,7 +94913,7 @@ module.exports.stringToSign = stringToSign
  * for S3 presigned URLs
  *
  * Spec:
- * 
+ *
  *    <date>\n
  *    <resource>
  *
@@ -111095,7 +111095,7 @@ var CacheObject = function (conf) {
     conf = conf || {};
     conf.ttl = parseInt(conf.ttl, 10) || 300; //0 is not permissible
     conf.cachesize = parseInt(conf.cachesize, 10) || 1000; //0 is not permissible
-    
+
     this.ttl = conf.ttl * 1000;
     this.max = conf.cachesize;
 
@@ -111236,7 +111236,7 @@ var EnhanceDns = function (conf) {
             //cache already exists, means this code has already execute ie method are already overwritten
             return dns;
         }
-        
+
         // original function storage
         var backup_object = {
                 lookup : dns.lookup,
@@ -111252,7 +111252,7 @@ var EnhanceDns = function (conf) {
             },
             // cache storage instance
             cache = conf.cache ? /*istanbul ignore next*/ new conf.cache(conf) : new CacheObject(conf);
-        
+
         // insert cache object to the instance
         dns.internalCache = cache;
 
@@ -112818,8 +112818,8 @@ var util = __webpack_require__(3)
   , net = __webpack_require__(164)
   , tls = __webpack_require__(466)
   , AgentSSL = __webpack_require__(195).Agent
-  
-function getConnectionName(host, port) {  
+
+function getConnectionName(host, port) {
   var name = ''
   if (typeof host === 'string') {
     name = host + ':' + port
@@ -112828,7 +112828,7 @@ function getConnectionName(host, port) {
     name = host.host + ':' + host.port + ':' + (host.localAddress ? (host.localAddress + ':') : ':')
   }
   return name
-}    
+}
 
 function ForeverAgent(options) {
   var self = this
@@ -112846,7 +112846,7 @@ function ForeverAgent(options) {
     } else if (self.sockets[name].length < self.minSockets) {
       if (!self.freeSockets[name]) self.freeSockets[name] = []
       self.freeSockets[name].push(socket)
-      
+
       // if an error happens while we don't use the socket anyway, meh, throw the socket away
       var onIdleError = function() {
         socket.destroy()
@@ -112872,7 +112872,7 @@ ForeverAgent.prototype.createConnection = net.createConnection
 ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest
 ForeverAgent.prototype.addRequest = function(req, host, port) {
   var name = getConnectionName(host, port)
-  
+
   if (typeof host !== 'string') {
     var options = host
     port = options.port
@@ -112901,7 +112901,7 @@ ForeverAgent.prototype.removeSocket = function(s, name, host, port) {
     delete this.sockets[name]
     delete this.requests[name]
   }
-  
+
   if (this.freeSockets[name]) {
     var index = this.freeSockets[name].indexOf(s)
     if (index !== -1) {
@@ -119628,7 +119628,7 @@ function DBCSCodec(codecOptions, iconv) {
     this.decodeTables = [];
     this.decodeTables[0] = UNASSIGNED_NODE.slice(0); // Create root node.
 
-    // Sometimes a MBCS char corresponds to a sequence of unicode chars. We store them as arrays of integers here. 
+    // Sometimes a MBCS char corresponds to a sequence of unicode chars. We store them as arrays of integers here.
     this.decodeTableSeq = [];
 
     // Actual mapping tables consist of chunks. Use them to fill up decode tables.
@@ -119637,7 +119637,7 @@ function DBCSCodec(codecOptions, iconv) {
 
     this.defaultCharUnicode = iconv.defaultCharUnicode;
 
-    
+
     // Encode tables: Unicode -> DBCS.
 
     // `encodeTable` is array mapping from unicode char to encoded char. All its values are integers for performance.
@@ -119646,7 +119646,7 @@ function DBCSCodec(codecOptions, iconv) {
     //         == UNASSIGNED -> no conversion found. Output a default char.
     //         <= SEQ_START  -> it's an index in encodeTableSeq, see below. The character starts a sequence.
     this.encodeTable = [];
-    
+
     // `encodeTableSeq` is used when a sequence of unicode characters is encoded as a single code. We use a tree of
     // objects where keys correspond to characters in sequence and leafs are the encoded dbcs values. A special DEF_CHAR key
     // means end of sequence (needed when one sequence is a strict subsequence of another).
@@ -119664,7 +119664,7 @@ function DBCSCodec(codecOptions, iconv) {
                 for (var j = val.from; j <= val.to; j++)
                     skipEncodeChars[j] = true;
         }
-        
+
     // Use decode trie to recursively fill out encode tables.
     this._fillEncodeTable(0, 0, skipEncodeChars);
 
@@ -119701,7 +119701,7 @@ function DBCSCodec(codecOptions, iconv) {
             thirdByteNode[i] = NODE_START - fourthByteNodeIdx;
         for (var i = 0x30; i <= 0x39; i++)
             fourthByteNode[i] = GB18030_CODE
-    }        
+    }
 }
 
 DBCSCodec.prototype.encoder = DBCSEncoder;
@@ -119766,7 +119766,7 @@ DBCSCodec.prototype._addDecodeChunk = function(chunk) {
                 else
                     writeTable[curAddr++] = code; // Basic char
             }
-        } 
+        }
         else if (typeof part === "number") { // Integer, meaning increasing sequence starting with prev character.
             var charCode = writeTable[curAddr - 1] + 1;
             for (var l = 0; l < part; l++)
@@ -119797,7 +119797,7 @@ DBCSCodec.prototype._setEncodeChar = function(uCode, dbcsCode) {
 }
 
 DBCSCodec.prototype._setEncodeSequence = function(seq, dbcsCode) {
-    
+
     // Get the root of character tree according to first character of the sequence.
     var uCode = seq[0];
     var bucket = this._getEncodeBucket(uCode);
@@ -119858,7 +119858,7 @@ function DBCSEncoder(options, codec) {
     // Encoder state
     this.leadSurrogate = -1;
     this.seqObj = undefined;
-    
+
     // Static data
     this.encodeTable = codec.encodeTable;
     this.encodeTableSeq = codec.encodeTableSeq;
@@ -119880,7 +119880,7 @@ DBCSEncoder.prototype.write = function(str) {
         }
         else {
             var uCode = nextChar;
-            nextChar = -1;    
+            nextChar = -1;
         }
 
         // 1. Handle surrogates.
@@ -119902,7 +119902,7 @@ DBCSEncoder.prototype.write = function(str) {
                     // Incomplete surrogate pair - only trail surrogate found.
                     uCode = UNASSIGNED;
                 }
-                
+
             }
         }
         else if (leadSurrogate !== -1) {
@@ -119943,7 +119943,7 @@ DBCSEncoder.prototype.write = function(str) {
             var subtable = this.encodeTable[uCode >> 8];
             if (subtable !== undefined)
                 dbcsCode = subtable[uCode & 0xFF];
-            
+
             if (dbcsCode <= SEQ_START) { // Sequence start
                 seqObj = this.encodeTableSeq[SEQ_START-dbcsCode];
                 continue;
@@ -119966,7 +119966,7 @@ DBCSEncoder.prototype.write = function(str) {
         // 3. Write dbcsCode character.
         if (dbcsCode === UNASSIGNED)
             dbcsCode = this.defaultCharSingleByte;
-        
+
         if (dbcsCode < 0x100) {
             newBuf[j++] = dbcsCode;
         }
@@ -120013,7 +120013,7 @@ DBCSEncoder.prototype.end = function() {
         newBuf[j++] = this.defaultCharSingleByte;
         this.leadSurrogate = -1;
     }
-    
+
     return newBuf.slice(0, j);
 }
 
@@ -120037,21 +120037,21 @@ function DBCSDecoder(options, codec) {
 
 DBCSDecoder.prototype.write = function(buf) {
     var newBuf = Buffer.alloc(buf.length*2),
-        nodeIdx = this.nodeIdx, 
+        nodeIdx = this.nodeIdx,
         prevBuf = this.prevBuf, prevBufOffset = this.prevBuf.length,
         seqStart = -this.prevBuf.length, // idx of the start of current parsed sequence.
         uCode;
 
     if (prevBufOffset > 0) // Make prev buf overlap a little to make it easier to slice later.
         prevBuf = Buffer.concat([prevBuf, buf.slice(0, 10)]);
-    
+
     for (var i = 0, j = 0; i < buf.length; i++) {
         var curByte = (i >= 0) ? buf[i] : prevBuf[i + prevBufOffset];
 
         // Lookup in current trie node.
         var uCode = this.decodeTables[nodeIdx][curByte];
 
-        if (uCode >= 0) { 
+        if (uCode >= 0) {
             // Normal character, just use it.
         }
         else if (uCode === UNASSIGNED) { // Unknown char.
@@ -120083,7 +120083,7 @@ DBCSDecoder.prototype.write = function(buf) {
             throw new Error("iconv-lite internal error: invalid decoding table value " + uCode + " at " + nodeIdx + "/" + curByte);
 
         // Write the character to buffer, handling higher planes using surrogate pair.
-        if (uCode > 0xFFFF) { 
+        if (uCode > 0xFFFF) {
             uCode -= 0x10000;
             var uCodeLead = 0xD800 + Math.floor(uCode / 0x400);
             newBuf[j++] = uCodeLead & 0xFF;
@@ -120153,11 +120153,11 @@ function findIdx(table, val) {
 // require()-s are direct to support Browserify.
 
 module.exports = {
-    
+
     // == Japanese/ShiftJIS ====================================================
     // All japanese encodings are based on JIS X set of standards:
     // JIS X 0201 - Single-byte encoding of ASCII + ¥ + Kana chars at 0xA1-0xDF.
-    // JIS X 0208 - Main set of 6879 characters, placed in 94x94 plane, to be encoded by 2 bytes. 
+    // JIS X 0208 - Main set of 6879 characters, placed in 94x94 plane, to be encoded by 2 bytes.
     //              Has several variations in 1978, 1983, 1990 and 1997.
     // JIS X 0212 - Supplementary plane of 6067 chars in 94x94 plane. 1990. Effectively dead.
     // JIS X 0213 - Extension and modern replacement of 0208 and 0212. Total chars: 11233.
@@ -120175,7 +120175,7 @@ module.exports = {
     //               0x8F, (0xA1-0xFE)x2 - 0212 plane (94x94).
     //  * JIS X 208: 7-bit, direct encoding of 0208. Byte ranges: 0x21-0x7E (94 values). Uncommon.
     //               Used as-is in ISO2022 family.
-    //  * ISO2022-JP: Stateful encoding, with escape sequences to switch between ASCII, 
+    //  * ISO2022-JP: Stateful encoding, with escape sequences to switch between ASCII,
     //                0201-1976 Roman, 0208-1978, 0208-1983.
     //  * ISO2022-JP-1: Adds esc seq for 0212-1990.
     //  * ISO2022-JP-2: Adds esc seq for GB2313-1980, KSX1001-1992, ISO8859-1, ISO8859-7.
@@ -120287,7 +120287,7 @@ module.exports = {
     //  * Windows CP 951: Microsoft variant of Big5-HKSCS-2001. Seems to be never public. http://me.abelcheung.org/articles/research/what-is-cp951/
     //  * Big5-2003 (Taiwan standard) almost superset of cp950.
     //  * Unicode-at-on (UAO) / Mozilla 1.8. Falling out of use on the Web. Not supported by other browsers.
-    //  * Big5-HKSCS (-2001, -2004, -2008). Hong Kong standard. 
+    //  * Big5-HKSCS (-2001, -2004, -2008). Hong Kong standard.
     //    many unicode code points moved from PUA to Supplementary plane (U+2XXXX) over the years.
     //    Plus, it has 4 combining sequences.
     //    Seems that Mozilla refused to support it for 10 yrs. https://bugzilla.mozilla.org/show_bug.cgi?id=162431 https://bugzilla.mozilla.org/show_bug.cgi?id=310299
@@ -120298,7 +120298,7 @@ module.exports = {
     //    In the encoder, it might make sense to support encoding old PUA mappings to Big5 bytes seq-s.
     //    Official spec: http://www.ogcio.gov.hk/en/business/tech_promotion/ccli/terms/doc/2003cmp_2008.txt
     //                   http://www.ogcio.gov.hk/tc/business/tech_promotion/ccli/terms/doc/hkscs-2008-big5-iso.txt
-    // 
+    //
     // Current understanding of how to deal with Big5(-HKSCS) is in the Encoding Standard, http://encoding.spec.whatwg.org/#big5-encoder
     // Unicode mapping (http://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/OTHER/BIG5.TXT) is said to be wrong.
 
@@ -120344,7 +120344,7 @@ var modules = [
     __webpack_require__(711),
 ];
 
-// Put all encoding/alias/codec definitions to single object and export it. 
+// Put all encoding/alias/codec definitions to single object and export it.
 for (var i = 0; i < modules.length; i++) {
     var module = modules[i];
     for (var enc in module)
@@ -120496,7 +120496,7 @@ function InternalDecoderCesu8(options, codec) {
 }
 
 InternalDecoderCesu8.prototype.write = function(buf) {
-    var acc = this.acc, contBytes = this.contBytes, accBytes = this.accBytes, 
+    var acc = this.acc, contBytes = this.contBytes, accBytes = this.accBytes,
         res = '';
     for (var i = 0; i < buf.length; i++) {
         var curByte = buf[i];
@@ -120557,17 +120557,17 @@ InternalDecoderCesu8.prototype.end = function() {
 var Buffer = __webpack_require__(15).Buffer;
 
 // Single-byte codec. Needs a 'chars' string parameter that contains 256 or 128 chars that
-// correspond to encoded bytes (if 128 - then lower half is ASCII). 
+// correspond to encoded bytes (if 128 - then lower half is ASCII).
 
 exports._sbcs = SBCSCodec;
 function SBCSCodec(codecOptions, iconv) {
     if (!codecOptions)
         throw new Error("SBCS codec is called without the data.")
-    
+
     // Prepare char buffer for decoding.
     if (!codecOptions.chars || (codecOptions.chars.length !== 128 && codecOptions.chars.length !== 256))
         throw new Error("Encoding '"+codecOptions.type+"' has incorrect 'chars' (must be of len 128 or 256)");
-    
+
     if (codecOptions.chars.length === 128) {
         var asciiString = "";
         for (var i = 0; i < 128; i++)
@@ -120576,7 +120576,7 @@ function SBCSCodec(codecOptions, iconv) {
     }
 
     this.decodeBuf = Buffer.from(codecOptions.chars, 'ucs2');
-    
+
     // Encoding buffer.
     var encodeBuf = Buffer.alloc(65536, iconv.defaultCharSingleByte.charCodeAt(0));
 
@@ -120598,7 +120598,7 @@ SBCSEncoder.prototype.write = function(str) {
     var buf = Buffer.alloc(str.length);
     for (var i = 0; i < str.length; i++)
         buf[i] = this.encodeBuf[str.charCodeAt(i)];
-    
+
     return buf;
 }
 
@@ -121417,7 +121417,7 @@ Utf16Decoder.prototype.write = function(buf) {
         // Codec is not chosen yet. Accumulate initial bytes.
         this.initialBytes.push(buf);
         this.initialBytesLen += buf.length;
-        
+
         if (this.initialBytesLen < 16) // We need more bytes to use space heuristic (see below)
             return '';
 
@@ -121513,8 +121513,8 @@ Utf7Encoder.prototype.write = function(str) {
     // Naive implementation.
     // Non-direct chars are encoded as "+<base64>-"; single "+" char is encoded as "+-".
     return Buffer.from(str.replace(nonDirectChars, function(chunk) {
-        return "+" + (chunk === '+' ? '' : 
-            this.iconv.encode(chunk, 'utf16-be').toString('base64').replace(/=+$/, '')) 
+        return "+" + (chunk === '+' ? '' :
+            this.iconv.encode(chunk, 'utf16-be').toString('base64').replace(/=+$/, ''))
             + "-";
     }.bind(this)));
 }
@@ -121536,7 +121536,7 @@ var base64Chars = [];
 for (var i = 0; i < 256; i++)
     base64Chars[i] = base64Regex.test(String.fromCharCode(i));
 
-var plusChar = '+'.charCodeAt(0), 
+var plusChar = '+'.charCodeAt(0),
     minusChar = '-'.charCodeAt(0),
     andChar = '&'.charCodeAt(0);
 
@@ -121865,7 +121865,7 @@ module.exports = function (iconv) {
         }
 
         var nodeNativeEncodings = {
-            'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true, 
+            'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true,
             'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
         };
 
@@ -122089,7 +122089,7 @@ iconv.encode = function encode(str, encoding, options) {
 
     var res = encoder.write(str);
     var trail = encoder.end();
-    
+
     return (trail && trail.length > 0) ? Buffer.concat([res, trail]) : res;
 }
 
@@ -122129,7 +122129,7 @@ iconv._codecDataCache = {};
 iconv.getCodec = function getCodec(encoding) {
     if (!iconv.encodings)
         iconv.encodings = __webpack_require__(712); // Lazy load all encoding definitions.
-    
+
     // Canonicalize encoding name: strip all non-alphanumeric chars and appended year.
     var enc = iconv._canonicalizeEncoding(encoding);
 
@@ -122153,7 +122153,7 @@ iconv.getCodec = function getCodec(encoding) {
 
                 if (!codecOptions.encodingName)
                     codecOptions.encodingName = enc;
-                
+
                 enc = codecDef.type;
                 break;
 
@@ -122232,7 +122232,7 @@ var Buffer = __webpack_require__(64).Buffer,
 
 // == Exports ==================================================================
 module.exports = function(iconv) {
-    
+
     // Additional Public API.
     iconv.encodeStream = function encodeStream(encoding, options) {
         return new IconvLiteEncoderStream(iconv.getEncoder(encoding, options), options);
@@ -122327,7 +122327,7 @@ IconvLiteDecoderStream.prototype._transform = function(chunk, encoding, done) {
 IconvLiteDecoderStream.prototype._flush = function(done) {
     try {
         var res = this.conv.end();
-        if (res && res.length) this.push(res, this.encoding);                
+        if (res && res.length) this.push(res, this.encoding);
         done();
     }
     catch (e) {
@@ -122974,8 +122974,8 @@ var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*O
 			if(typeof instance != 'object' || instance instanceof Array){
 				errors.push({property:path,message:"an object is required"});
 			}
-			
-			for(var i in objTypeDef){ 
+
+			for(var i in objTypeDef){
 				if(objTypeDef.hasOwnProperty(i)){
 					var value = instance[i];
 					// skip _not_ specified properties
@@ -128134,7 +128134,7 @@ Emoji.replace = function replace (str, replacement, cleanSpaces) {
 
   var replaced = words.map(function(word, idx) {
     var emoji = Emoji.findByCode(word);
-    
+
     if (emoji && cleanSpaces && words[idx + 1] === ' ') {
       words[idx + 1] = '';
     }
@@ -128450,7 +128450,7 @@ function compare (a, b) {
 }
 
 function generateBase (httpMethod, base_uri, params) {
-  // adapted from https://dev.twitter.com/docs/auth/oauth and 
+  // adapted from https://dev.twitter.com/docs/auth/oauth and
   // https://dev.twitter.com/docs/auth/creating-signature
 
   // Parameter normalization
@@ -145421,7 +145421,7 @@ function fileSync(options) {
   const name = tmpNameSync(opts);
   var fd = fs.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
   if (opts.discardDescriptor) {
-    fs.closeSync(fd); 
+    fs.closeSync(fd);
     fd = undefined;
   }
 
@@ -147120,4 +147120,4 @@ module.exports = require("dns");
 module.exports = require("domain");
 
 /***/ })
-/******/ ]);
+/******/ ]);

+ 6 - 7
conftest.py

@@ -6,24 +6,23 @@ from hashlib import md5
 
 import pytest
 
-pytest_plugins = [
-    'sentry.utils.pytest'
-]
+pytest_plugins = ["sentry.utils.pytest"]
 
-sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
 
 
 def pytest_configure(config):
     import warnings
+
     # XXX(dcramer): Riak throws a UserWarning re:OpenSSL which isnt important
     # to tests
     # XXX(dramer): Kombu throws a warning due to transaction.commit_manually
     # being used
-    warnings.filterwarnings('error', '', Warning, r'^(?!(|kombu|raven|riak|sentry))')
+    warnings.filterwarnings("error", "", Warning, r"^(?!(|kombu|raven|riak|sentry))")
 
 
 def pytest_collection_modifyitems(items):
     for item in items:
-        total_groups = int(os.environ.get('TOTAL_TEST_GROUPS', 1))
+        total_groups = int(os.environ.get("TOTAL_TEST_GROUPS", 1))
         group_num = int(md5(item.location[0]).hexdigest(), 16) % total_groups
-        item.add_marker(getattr(pytest.mark, 'group_%s' % group_num))
+        item.add_marker(getattr(pytest.mark, "group_%s" % group_num))

+ 38 - 45
examples/oauth2_consumer_webserver/app.py

@@ -7,12 +7,12 @@ import six
 from flask import Flask, redirect, url_for, request, session
 from flask_oauth import OAuth
 
-BASE_URL = os.environ.get('BASE_URL', 'http://dev.getsentry.net:8000')
-CLIENT_ID = os.environ.get('CLIENT_ID')
-CLIENT_SECRET = os.environ.get('CLIENT_SECRET')
-REDIRECT_URI = '/authorized'
+BASE_URL = os.environ.get("BASE_URL", "http://dev.getsentry.net:8000")
+CLIENT_ID = os.environ.get("CLIENT_ID")
+CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
+REDIRECT_URI = "/authorized"
 
-SECRET_KEY = 'development key'
+SECRET_KEY = "development key"
 DEBUG = True
 
 app = Flask(__name__)
@@ -21,82 +21,75 @@ app.secret_key = SECRET_KEY
 oauth = OAuth()
 
 sentry = oauth.remote_app(
-    'sentry',
+    "sentry",
     base_url=BASE_URL,
-    authorize_url='{}/oauth/authorize/'.format(BASE_URL),
+    authorize_url="{}/oauth/authorize/".format(BASE_URL),
     request_token_url=None,
     request_token_params={
-        'scope': 'project:releases event:read org:read org:write',
-        'response_type': 'code'
-    },
-    access_token_url='{}/oauth/token/'.format(BASE_URL),
-    access_token_method='POST',
-    access_token_params={
-        'grant_type': 'authorization_code',
+        "scope": "project:releases event:read org:read org:write",
+        "response_type": "code",
     },
+    access_token_url="{}/oauth/token/".format(BASE_URL),
+    access_token_method="POST",
+    access_token_params={"grant_type": "authorization_code"},
     consumer_key=CLIENT_ID,
     consumer_secret=CLIENT_SECRET,
 )
 
 
-@app.route('/')
+@app.route("/")
 def index():
-    access_token = session.get('access_token')
+    access_token = session.get("access_token")
     if access_token is None:
-        return ('<h1>Who are you?</h1>'
-                '<p><a href="{}">Login with Sentry</a></p>').format(
-                    url_for('login'),
-                )
+        return ("<h1>Who are you?</h1>" '<p><a href="{}">Login with Sentry</a></p>').format(
+            url_for("login")
+        )
 
     from urllib2 import Request, urlopen, URLError
-    headers = {'Authorization': 'Bearer {}'.format(access_token)}
-    req = Request('{}/api/0/organizations/'.format(BASE_URL), None, headers)
+
+    headers = {"Authorization": "Bearer {}".format(access_token)}
+    req = Request("{}/api/0/organizations/".format(BASE_URL), None, headers)
     try:
         res = urlopen(req)
     except URLError as e:
         if e.code == 401:
             # Unauthorized - bad token
-            session.pop('access_token', None)
-            return redirect(url_for('login'))
-        return '{}\n{}'.format(six.text_type(e), e.read())
+            session.pop("access_token", None)
+            return redirect(url_for("login"))
+        return "{}\n{}".format(six.text_type(e), e.read())
 
-    return ('<h1>Hi, {}!</h1>'
-            '<pre>{}</pre>').format(
-                json.loads(session['user'])['email'],
-                json.dumps(json.loads(res.read()), indent=2),
-            )
+    return ("<h1>Hi, {}!</h1>" "<pre>{}</pre>").format(
+        json.loads(session["user"])["email"], json.dumps(json.loads(res.read()), indent=2)
+    )
 
 
-@app.route('/login')
+@app.route("/login")
 def login():
-    callback = url_for('authorized', _external=True)
+    callback = url_for("authorized", _external=True)
     return sentry.authorize(callback=callback)
 
 
 @app.route(REDIRECT_URI)
 @sentry.authorized_handler
 def authorized(resp):
-    if 'error' in request.args:
-        return ('<h1>Error</h1>'
-                '<p>{}</p>'
-                '<p><a href="{}">Try again</a></p>').format(
-                    request.args['error'],
-                    url_for('login'),
-                )
-    access_token = resp['access_token']
-    session['access_token'] = access_token
-    session['user'] = json.dumps(resp['user'])
-    return redirect(url_for('index'))
+    if "error" in request.args:
+        return ("<h1>Error</h1>" "<p>{}</p>" '<p><a href="{}">Try again</a></p>').format(
+            request.args["error"], url_for("login")
+        )
+    access_token = resp["access_token"]
+    session["access_token"] = access_token
+    session["user"] = json.dumps(resp["user"])
+    return redirect(url_for("index"))
 
 
 @sentry.tokengetter
 def get_access_token():
-    return session.get('access_token')
+    return session.get("access_token")
 
 
 def main():
     app.run()
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()

+ 5 - 0
pyproject.toml

@@ -0,0 +1,5 @@
+[tool.black]
+line-length=100
+target-version=['py27']
+include='\.py$'
+exclude='(.eggs|.git|.venv|build|dist|south_migrations|node_modules)'

+ 3 - 1
setup.cfg

@@ -8,8 +8,10 @@ markers =
     snuba: mark a test as requiring snuba
 
 [flake8]
-ignore = F999,E501,E128,E124,E402,W503,E731,C901,B007,B306,B009,B010
+# E203 false positive, see https://github.com/PyCQA/pycodestyle/issues/373
+ignore = F999,E203,E501,E128,E124,E402,W503,E731,C901,B007,B306,B009,B010
 max-line-length = 100
+# TODO: mirror this in pre-commit exclude flavor regex
 exclude = .venv/.git,*/south_migrations/*,node_modules/*,src/sentry/static/sentry/vendor/*,docs/*,src/south/*,examples/*
 
 [bdist_wheel]

+ 55 - 58
setup.py

@@ -37,50 +37,50 @@ from setuptools import setup, find_packages
 from setuptools.command.sdist import sdist as SDistCommand
 from setuptools.command.develop import develop as DevelopCommand
 
-ROOT = os.path.realpath(os.path.join(os.path.dirname(
-    sys.modules['__main__'].__file__)))
+ROOT = os.path.realpath(os.path.join(os.path.dirname(sys.modules["__main__"].__file__)))
 
 # Add Sentry to path so we can import distutils
-sys.path.insert(0, os.path.join(ROOT, 'src'))
+sys.path.insert(0, os.path.join(ROOT, "src"))
 
 from sentry.utils.distutils import (
-    BuildAssetsCommand, BuildIntegrationDocsCommand, BuildJsSdkRegistryCommand
+    BuildAssetsCommand,
+    BuildIntegrationDocsCommand,
+    BuildJsSdkRegistryCommand,
 )
 
 # The version of sentry
-VERSION = '10.0.0.dev0'
+VERSION = "10.0.0.dev0"
 
 # Hack to prevent stupid "TypeError: 'NoneType' object is not callable" error
 # in multiprocessing/util.py _exit_function when running `python
 # setup.py test` (see
 # http://www.eby-sarna.com/pipermail/peak/2010-May/003357.html)
-for m in ('multiprocessing', 'billiard'):
+for m in ("multiprocessing", "billiard"):
     try:
         __import__(m)
     except ImportError:
         pass
 
-IS_LIGHT_BUILD = os.environ.get('SENTRY_LIGHT_BUILD') == '1'
+IS_LIGHT_BUILD = os.environ.get("SENTRY_LIGHT_BUILD") == "1"
 
 # we use pip requirements files to improve Docker layer caching
 
 
 def get_requirements(env):
-    with open(u'requirements-{}.txt'.format(env)) as fp:
-        return [x.strip() for x in fp.read().split('\n') if not x.startswith('#')]
+    with open(u"requirements-{}.txt".format(env)) as fp:
+        return [x.strip() for x in fp.read().split("\n") if not x.startswith("#")]
 
 
-install_requires = get_requirements('base')
-dev_requires = get_requirements('dev')
-tests_require = get_requirements('test')
-optional_requires = get_requirements('optional')
+install_requires = get_requirements("base")
+dev_requires = get_requirements("dev")
+tests_require = get_requirements("test")
+optional_requires = get_requirements("optional")
 
 # override django version in requirements file if DJANGO_VERSION is set
-DJANGO_VERSION = os.environ.get('DJANGO_VERSION')
+DJANGO_VERSION = os.environ.get("DJANGO_VERSION")
 if DJANGO_VERSION:
     install_requires = [
-        u'Django{}'.format(DJANGO_VERSION)
-        if r.startswith('Django>=') else r
+        u"Django{}".format(DJANGO_VERSION) if r.startswith("Django>=") else r
         for r in install_requires
     ]
 
@@ -89,18 +89,19 @@ class SentrySDistCommand(SDistCommand):
     # If we are not a light build we want to also execute build_assets as
     # part of our source build pipeline.
     if not IS_LIGHT_BUILD:
-        sub_commands = SDistCommand.sub_commands + \
-            [('build_integration_docs', None),
-             ('build_assets', None),
-             ('build_js_sdk_registry', None)]
+        sub_commands = SDistCommand.sub_commands + [
+            ("build_integration_docs", None),
+            ("build_assets", None),
+            ("build_js_sdk_registry", None),
+        ]
 
 
 class SentryBuildCommand(BuildCommand):
     def run(self):
         if not IS_LIGHT_BUILD:
-            self.run_command('build_integration_docs')
-            self.run_command('build_assets')
-            self.run_command('build_js_sdk_registry')
+            self.run_command("build_integration_docs")
+            self.run_command("build_assets")
+            self.run_command("build_js_sdk_registry")
         BuildCommand.run(self)
 
 
@@ -108,55 +109,51 @@ class SentryDevelopCommand(DevelopCommand):
     def run(self):
         DevelopCommand.run(self)
         if not IS_LIGHT_BUILD:
-            self.run_command('build_integration_docs')
-            self.run_command('build_assets')
-            self.run_command('build_js_sdk_registry')
+            self.run_command("build_integration_docs")
+            self.run_command("build_assets")
+            self.run_command("build_js_sdk_registry")
 
 
 cmdclass = {
-    'sdist': SentrySDistCommand,
-    'develop': SentryDevelopCommand,
-    'build': SentryBuildCommand,
-    'build_assets': BuildAssetsCommand,
-    'build_integration_docs': BuildIntegrationDocsCommand,
-    'build_js_sdk_registry': BuildJsSdkRegistryCommand,
+    "sdist": SentrySDistCommand,
+    "develop": SentryDevelopCommand,
+    "build": SentryBuildCommand,
+    "build_assets": BuildAssetsCommand,
+    "build_integration_docs": BuildIntegrationDocsCommand,
+    "build_js_sdk_registry": BuildJsSdkRegistryCommand,
 }
 
 
 setup(
-    name='sentry',
+    name="sentry",
     version=VERSION,
-    author='Sentry',
-    author_email='hello@sentry.io',
-    url='https://sentry.io',
-    description='A realtime logging and aggregation server.',
-    long_description=open(os.path.join(ROOT, 'README.rst')).read(),
-    package_dir={'': 'src'},
-    packages=find_packages('src'),
+    author="Sentry",
+    author_email="hello@sentry.io",
+    url="https://sentry.io",
+    description="A realtime logging and aggregation server.",
+    long_description=open(os.path.join(ROOT, "README.rst")).read(),
+    package_dir={"": "src"},
+    packages=find_packages("src"),
     zip_safe=False,
     install_requires=install_requires,
     extras_require={
-        'dev': dev_requires,
-        'postgres': [],
-        'tests': tests_require,
-        'optional': optional_requires,
+        "dev": dev_requires,
+        "postgres": [],
+        "tests": tests_require,
+        "optional": optional_requires,
     },
     cmdclass=cmdclass,
-    license='BSD',
+    license="BSD",
     include_package_data=True,
-    entry_points={
-        'console_scripts': [
-            'sentry = sentry.runner:main',
-        ],
-    },
+    entry_points={"console_scripts": ["sentry = sentry.runner:main"]},
     classifiers=[
-        'Framework :: Django',
-        'Intended Audience :: Developers',
-        'Intended Audience :: System Administrators',
-        'Operating System :: POSIX :: Linux',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 2 :: Only',
-        'Topic :: Software Development'
+        "Framework :: Django",
+        "Intended Audience :: Developers",
+        "Intended Audience :: System Administrators",
+        "Operating System :: POSIX :: Linux",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 2 :: Only",
+        "Topic :: Software Development",
     ],
 )

Some files were not shown because too many files changed in this diff