Hello community,

here is the log from the commit of package python-django-silk for 
openSUSE:Factory checked in at 2020-02-20 14:59:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-silk (Old)
 and      /work/SRC/openSUSE:Factory/.python-django-silk.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-django-silk"

Thu Feb 20 14:59:39 2020 rev:5 rq:777606 version:4.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-django-silk/python-django-silk.changes    
2019-09-17 13:37:31.401841766 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-django-silk.new.26092/python-django-silk.changes
 2020-02-20 14:59:43.218799002 +0100
@@ -1,0 +2,12 @@
+Thu Feb 20 09:08:46 UTC 2020 - Tomáš Chvátal <[email protected]>
+
+- Update to 4.0.0:
+  * Ability to clean up all requests/queries #368 (nasirhjafri)
+  * Used bulk_create to save number of queries #370 (nasirhjafri)
+  * Dropped Python 2 and 3.4 support #380 (munza)
+  * Added Python 3.8 support #380 (nasirhjafri)
+  * Removed django<2.2 support and added django 3.0 support #385 (nasirhjafri)
+  * Add function support for enabling profiling #391 (tredzko)
+  * Mask authorization header #376 (StefanMich)
+
+-------------------------------------------------------------------

Old:
----
  django-silk-3.0.4.tar.gz

New:
----
  django-silk-4.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-django-silk.spec ++++++
--- /var/tmp/diff_new_pack.B02yLg/_old  2020-02-20 14:59:44.342801207 +0100
+++ /var/tmp/diff_new_pack.B02yLg/_new  2020-02-20 14:59:44.342801207 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-django-silk
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,16 +16,15 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%define skip_python2 1
 Name:           python-django-silk
-Version:        3.0.4
+Version:        4.0.0
 Release:        0
 Summary:        Profiling for the Django Framework
 License:        MIT
-Group:          Development/Languages/Python
-Url:            https://github.com/jazzband/django-silk
+URL:            https://github.com/jazzband/django-silk
 Source:         
https://github.com/jazzband/django-silk/archive/%{version}.tar.gz#/django-silk-%{version}.tar.gz
-BuildRequires:  %{python_module Django >= 1.11}
+BuildRequires:  %{python_module Django >= 2.2}
 BuildRequires:  %{python_module Jinja2 >= 2.8}
 BuildRequires:  %{python_module Pillow >= 3.2}
 BuildRequires:  %{python_module Pygments >= 2.0}
@@ -36,7 +35,19 @@
 BuildRequires:  %{python_module requests >= 2.10}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module sqlparse >= 0.1.19}
+BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
+Requires:       python-Django >= 2.2
+Requires:       python-Jinja2 >= 2.8
+Requires:       python-Pillow >= 3.2
+Requires:       python-Pygments >= 2.0
+Requires:       python-autopep8 >= 1.2.1
+Requires:       python-gprof2dot >= 2017.09.19
+Requires:       python-python-dateutil >= 2.4
+Requires:       python-pytz > 2014.2
+Requires:       python-requests >= 2.10
+Requires:       python-sqlparse >= 0.1.19
+BuildArch:      noarch
 # SECTION test requirements
 BuildRequires:  %{python_module contextlib2 >= 0.5.5}
 BuildRequires:  %{python_module factory_boy >= 2.8.1}
@@ -48,19 +59,6 @@
 BuildRequires:  %{python_module simplejson >= 3.13.2}
 BuildRequires:  %{python_module six >= 1.11.0}
 # /SECTION
-BuildRequires:  fdupes
-Requires:       python-Django >= 1.11
-Requires:       python-Jinja2 >= 2.8
-Requires:       python-Pillow >= 3.2
-Requires:       python-Pygments >= 2.0
-Requires:       python-autopep8 >= 1.2.1
-Requires:       python-gprof2dot >= 2017.09.19
-Requires:       python-python-dateutil >= 2.4
-Requires:       python-pytz > 2014.2
-Requires:       python-requests >= 2.10
-Requires:       python-sqlparse >= 0.1.19
-BuildArch:      noarch
-
 %python_subpackages
 
 %description

++++++ django-silk-3.0.4.tar.gz -> django-silk-4.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/.travis.yml 
new/django-silk-4.0.0/.travis.yml
--- old/django-silk-3.0.4/.travis.yml   2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/.travis.yml   2020-01-21 09:09:29.000000000 +0100
@@ -2,60 +2,25 @@
 dist: xenial
 sudo: false
 python:
-- '2.7'
-- '3.4'
 - '3.5'
 - '3.6'
 - '3.7'
+- '3.8'
 env:
-- DJANGO="Django>=1.11.0,<2.0"    DB=postgresql DB_NAME=travis_ci_test
-- DJANGO="Django>=2.0,<2.1.0"     DB=postgresql DB_NAME=travis_ci_test
-- DJANGO="Django>=2.1,<2.2.0"     DB=postgresql DB_NAME=travis_ci_test
 - DJANGO="Django>=2.2,<2.3.0"     DB=postgresql DB_NAME=travis_ci_test
-- DJANGO="Django>=1.11.0,<2.0"    DB=sqlite3 DB_NAME=db.sqlite3
-- DJANGO="Django>=2.0,<2.1.0"     DB=sqlite3 DB_NAME=db.sqlite3
-- DJANGO="Django>=2.1,<2.2.0"     DB=sqlite3 DB_NAME=db.sqlite3
+- DJANGO="Django>=3.0"            DB=postgresql DB_NAME=travis_ci_test
 - DJANGO="Django>=2.2,<2.3.0"     DB=sqlite3 DB_NAME=db.sqlite3
-- DJANGO="Django>=1.11.0,<2.0"    DB=mysql DB_NAME=mysql_db
-- DJANGO="Django>=2.0,<2.1.0"     DB=mysql DB_NAME=mysql_db
-- DJANGO="Django>=2.1,<2.2.0"     DB=mysql DB_NAME=mysql_db
+- DJANGO="Django>=3.0"            DB=sqlite3 DB_NAME=db.sqlite3
 - DJANGO="Django>=2.2,<2.3.0"     DB=mysql DB_NAME=mysql_db
+- DJANGO="Django>=3.0"            DB=mysql DB_NAME=mysql_db
 matrix:
   exclude:
-  - python: '2.7'
-    env: DJANGO="Django>=2.0,<2.1.0"     DB=postgresql DB_NAME=travis_ci_test
-  - python: '2.7'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=postgresql DB_NAME=travis_ci_test
-  - python: '2.7'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=postgresql DB_NAME=travis_ci_test
-  - python: '2.7'
-    env: DJANGO="Django>=2.0,<2.1.0"     DB=sqlite3 DB_NAME=db.sqlite3
-  - python: '2.7'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=sqlite3 DB_NAME=db.sqlite3
-  - python: '2.7'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=sqlite3 DB_NAME=db.sqlite3
-  - python: '2.7'
-    env: DJANGO="Django>=2.0,<2.1.0"     DB=mysql DB_NAME=mysql_db
-  - python: '2.7'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=mysql DB_NAME=mysql_db
-  - python: '2.7'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=mysql DB_NAME=mysql_db
-  - python: '3.4'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=postgresql DB_NAME=travis_ci_test
-  - python: '3.4'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=postgresql DB_NAME=travis_ci_test
-  - python: '3.4'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=sqlite3 DB_NAME=db.sqlite3
-  - python: '3.4'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=sqlite3 DB_NAME=db.sqlite3
-  - python: '3.4'
-    env: DJANGO="Django>=1.11.0,<2.0"    DB=mysql DB_NAME=mysql_db
-  - python: '3.4'
-    env: DJANGO="Django>=2.0,<2.1.0"     DB=mysql DB_NAME=mysql_db
-  - python: '3.4'
-    env: DJANGO="Django>=2.1,<2.2.0"     DB=mysql DB_NAME=mysql_db
-  - python: '3.4'
-    env: DJANGO="Django>=2.2,<2.3.0"     DB=mysql DB_NAME=mysql_db
+  - python: '3.5'
+    env: DJANGO="Django>=3.0"            DB=postgresql DB_NAME=travis_ci_test
+  - python: '3.5'
+    env: DJANGO="Django>=3.0"            DB=sqlite3 DB_NAME=db.sqlite3
+  - python: '3.5'
+    env: DJANGO="Django>=3.0"            DB=mysql DB_NAME=mysql_db
   fast_finish: true
 services:
   - mysql
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/CHANGELOG.md 
new/django-silk-4.0.0/CHANGELOG.md
--- old/django-silk-3.0.4/CHANGELOG.md  2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/CHANGELOG.md  2020-01-21 09:09:29.000000000 +0100
@@ -1,5 +1,43 @@
 # Change Log
 
+
+## [4.0.0](https://github.com/jazzband/django-silk/tree/4.0.0) (2020-01-09)
+
+[Full Changelog](https://github.com/jazzband/django-silk/compare/3.0.4...4.0.0)
+
+**New features/Implemented enhancements:**
+
+- Ability to clean up all requests/queries 
[\#368](https://github.com/jazzband/django-silk/pull/368) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Used bulk_create to save number of queries 
[\#370](https://github.com/jazzband/django-silk/pull/370) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Dropped Python 2 and 3.4 support 
[\#380](https://github.com/jazzband/django-silk/pull/380) 
([munza](https://github.com/munza))
+- Added Python 3.8 support 
[\#380](https://github.com/jazzband/django-silk/pull/380) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Removed django<2.2 support and added django 3.0 support 
[\#385](https://github.com/jazzband/django-silk/pull/385) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Add function support for enabling profiling 
[\#391](https://github.com/jazzband/django-silk/pull/391) 
([tredzko](https://github.com/tredzko))
+
+**Fixed bugs:**
+
+- Mask authorization header 
[\#376](https://github.com/jazzband/django-silk/pull/376) 
([StefanMich](https://github.com/StefanMich))
+
+**Closed issues:**
+
+- Ability to clean up all requests/queries 
[\#365](https://github.com/jazzband/django-silk/issues/365)
+- Use bulk_create to save number of queries 
[\#369](https://github.com/jazzband/django-silk/issues/369)
+- Headers are not sanitized 
[\#375](https://github.com/jazzband/django-silk/issues/375)
+- Django 3 support [\#382](https://github.com/jazzband/django-silk/issues/382)
+- Support functional cProfile enable 
[\#390](https://github.com/jazzband/django-silk/issues/390)
+
+
+**Merged pull requests:**
+
+- Mask authorization header 
[\#376](https://github.com/jazzband/django-silk/pull/376) 
([StefanMich](https://github.com/StefanMich))
+- Ability to clean up all requests/queries 
[\#368](https://github.com/jazzband/django-silk/pull/368) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Used bulk_create to save number of queries 
[\#370](https://github.com/jazzband/django-silk/pull/370) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Dropped Python 2 and 3.4 support 
[\#380](https://github.com/jazzband/django-silk/pull/380) 
([munza](https://github.com/munza))
+- Added Python 3.8 support 
[\#380](https://github.com/jazzband/django-silk/pull/380) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Removed django<2.2 support and added django 3.0 support 
[\#385](https://github.com/jazzband/django-silk/pull/385) 
([nasirhjafri](https://github.com/nasirhjafri))
+- Add function support for enabling profiling 
[\#391](https://github.com/jazzband/django-silk/pull/391) 
([tredzko](https://github.com/tredzko))
+
+
 ## [3.0.4](https://github.com/jazzband/django-silk/tree/3.0.4) (2019-08-12)
 
 [Full Changelog](https://github.com/jazzband/django-silk/compare/3.0.2...3.0.4)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/README.md 
new/django-silk-4.0.0/README.md
--- old/django-silk-3.0.4/README.md     2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/README.md     2020-01-21 09:09:29.000000000 +0100
@@ -1,9 +1,5 @@
 # Silk
 
-====
-
-*Silk has now moved to the [Jazzband](https://jazzband.co/) organization and 
is looking for contributors - if you think you can help out, please get in 
touch!*
-
 [![TravisCI 
Build](https://img.shields.io/travis/jazzband/django-silk/master.svg)](https://travis-ci.org/jazzband/django-silk)
 [![PyPI 
Download](https://img.shields.io/pypi/v/django-silk.svg)](https://pypi.python.org/pypi/django-silk)
 [![PyPI Python 
Versions](https://img.shields.io/pypi/pyversions/django-silk.svg)](https://pypi.python.org/pypi/django-silk)
@@ -34,8 +30,8 @@
 
 Silk has been tested with:
 
-* Django: 1.11, 2.0, 2.1, 2.2
-* Python: 2.7, 3.4, 3.5, 3.6, 3.7
+* Django: 2.2, 3.0
+* Python: 3.5, 3.6, 3.7, 3.8
 
 ## Installation
 
@@ -356,6 +352,26 @@
 it has already been imported, no profiling would be triggered.
 
 
+#### Custom Logic for Profiling
+
+Sometimes you may want to dynamically control when the profiler runs. You can 
write your own logic for when to enable the profiler. To do this add the 
following to your `settings.py`:
+
+This setting is mutually exclusive with SILKY_PYTHON_PROFILER and will be used 
over it if present. It will work with SILKY_DYNAMIC_PROFILING.
+
+```python
+def my_custom_logic(request):
+    return 'profile_requests' in request.session
+
+SILKY_PYTHON_PROFILER_FUNC = my_custom_logic # profile only session has 
recording enabled.
+```
+
+You can also use a `lambda`.
+
+```python
+# profile only session has recording enabled.
+SILKY_PYTHON_PROFILER_FUNC = lambda request: 'profile_requests' in 
request.session
+```
+
 ### Code Generation
 
 Silk currently generates two bits of code per request:
@@ -422,7 +438,7 @@
 
 ### Recording a Fraction of Requests
 
-On high-load sites it may be helpful to only record a fraction of the requests 
that are made.To do this add the following to your `settings.py`:
+On high-load sites it may be helpful to only record a fraction of the requests 
that are made. To do this add the following to your `settings.py`:
 
 Note: This setting is mutually exclusive with SILKY_INTERCEPT_FUNC.
 
@@ -432,7 +448,7 @@
 
 #### Custom Logic for Recording Requests
 
-On high-load sites it may also be helpful to write your own logic for when to 
intercept requests.To do this add the following to your `settings.py`:
+On high-load sites it may also be helpful to write your own logic for when to 
intercept requests. To do this add the following to your `settings.py`:
 
 Note: This setting is mutually exclusive with SILKY_INTERCEPT_PERCENT.
 
@@ -508,6 +524,12 @@
 
 For other combinations, check [`.travis.yml`](./.travis.yml).
 
+Now from the root of the sample `project` apply the migrations
+
+```bash
+python manage.py migrate
+```
+
 Now from the root of the sample `project` directory start the django server
 
 ```bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/docs/index.rst 
new/django-silk-4.0.0/docs/index.rst
--- old/django-silk-3.0.4/docs/index.rst        2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/docs/index.rst        2020-01-21 09:09:29.000000000 
+0100
@@ -57,5 +57,5 @@
 Requirements
 ------------
 
-* Django: 1.11, 2.0, 2.1, 2.2
-* Python: 2.7, 3.4, 3.5, 3.6, 3.7
+* Django: 2.2, 3.0
+* Python: 3.5, 3.6, 3.7, 3.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/package.json 
new/django-silk-4.0.0/package.json
--- old/django-silk-3.0.4/package.json  2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/package.json  2020-01-21 09:09:29.000000000 +0100
@@ -1,6 +1,6 @@
 {
   "name": "silk",
-  "version": "3.0.4",
+  "version": "4.0.0",
   "description": "https://github.com/jazzband/django-silk";,
   "main": "index.js",
   "directories": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/project/test-requirements.txt 
new/django-silk-4.0.0/project/test-requirements.txt
--- old/django-silk-3.0.4/project/test-requirements.txt 2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/project/test-requirements.txt 2020-01-21 
09:09:29.000000000 +0100
@@ -1,5 +1,4 @@
 Pygments>=2.0,<2.1
-six==1.11.0
 simplejson==3.13.2
 python-dateutil>=2.4,<2.5
 requests==2.21.0
@@ -10,7 +9,7 @@
 mock==2.0.0
 Pillow==5.4.1
 factory-boy==2.9.2
-freezegun==0.3.11
+freezegun==0.3.12
 networkx==1.11
 pydotplus==2.0.2
 contextlib2==0.5.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/project/tests/test_dynamic_profiling.py 
new/django-silk-4.0.0/project/tests/test_dynamic_profiling.py
--- old/django-silk-3.0.4/project/tests/test_dynamic_profiling.py       
2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/project/tests/test_dynamic_profiling.py       
2020-01-21 09:09:29.000000000 +0100
@@ -1,6 +1,5 @@
 from django.test import TestCase
 from mock import patch
-import six
 
 import silk
 from silk.profiling.dynamic import _get_module, _get_parent_module, 
profile_function_or_method
@@ -73,12 +72,12 @@
                     'dynamic': True,
                     'file_path': source_file_name(),
                     'name': 'test',
-                    'line_num': six.get_function_code(foo).co_firstlineno
+                    'line_num': foo.__code__.co_firstlineno
                 }, call_args)
 
     def test_func_as_str(self):
         name = foo.__name__
-        line_num = six.get_function_code(foo).co_firstlineno
+        line_num = foo.__code__.co_firstlineno
         profile_function_or_method('tests.test_dynamic_profiling', 'foo', 
'test')
         dc = mock_data_collector()
         with patch('silk.profiling.profiler.DataCollector', return_value=dc) 
as mock_DataCollector:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/project/tests/test_profile_dot.py 
new/django-silk-4.0.0/project/tests/test_profile_dot.py
--- old/django-silk-3.0.4/project/tests/test_profile_dot.py     2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/project/tests/test_profile_dot.py     2020-01-21 
09:09:29.000000000 +0100
@@ -3,11 +3,8 @@
 import cProfile
 import tempfile
 from contextlib import contextmanager
-from six import PY3
-if PY3:
-    from unittest.mock import MagicMock
-else:
-    from mock import MagicMock
+from unittest.mock import MagicMock
+
 # 3rd party
 from django.test import TestCase
 from networkx.drawing.nx_pydot import read_dot
@@ -80,8 +77,7 @@
                 # create dot
                 with tempfile.NamedTemporaryFile(delete=False) as dotfile:
                     dot = _create_dot(self._profile(), 5)
-                    dot = dot.encode('utf-8') if PY3 else dot
-                    dotfile.write(dot)
+                    dotfile.write(dot.encode('utf-8'))
 
                 # verify generated dot is valid
                 G = read_dot(dotfile.name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/project/tests/test_profile_parser.py 
new/django-silk-4.0.0/project/tests/test_profile_parser.py
--- old/django-silk-3.0.4/project/tests/test_profile_parser.py  2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/project/tests/test_profile_parser.py  2020-01-21 
09:09:29.000000000 +0100
@@ -2,10 +2,9 @@
 from __future__ import print_function
 # std
 import cProfile
-import sys
+from io import StringIO
 # 3rd party
 import contextlib2 as contextlib
-from six import StringIO, PY3
 from django.test import TestCase
 # silk
 from silk.utils.profile_parser import parse_profile
@@ -22,33 +21,11 @@
                 cProfile.run('print()')
             stream.seek(0)
             actual = list(parse_profile(stream))
-            if PY3:
-                if sys.version_info < (3,5):
-                    expected = [
-                         ['ncalls', 'tottime', 'percall', 'cumtime', 
'percall', 'filename:lineno(function)'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', 
'<string>:1(<module>)'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', '{built-in 
method exec}'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', '{built-in 
method print}'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', "{method 
'disable' of '_lsprof.Profiler' objects}"],
-                    ]
-                else:
-                    expected = [
-                         ['ncalls', 'tottime', 'percall', 'cumtime', 
'percall', 'filename:lineno(function)'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', 
'<string>:1(<module>)'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', '{built-in 
method builtins.exec}'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', '{built-in 
method builtins.print}'],
-                         ['1', '0.000', '0.000', '0.000', '0.000', "{method 
'disable' of '_lsprof.Profiler' objects}"],
-                    ]
-            else:
-                expected = [
-                    ['ncalls', 'tottime', 'percall', 'cumtime', 'percall', 
'filename:lineno(function)'],
-                    ['1', '0.000', '0.000', '0.000', '0.000', 
'<string>:1(<module>)'],
-                    ['2', '0.000', '0.000', '0.000', '0.000', 
'StringIO.py:208(write)'],
-                    ['2', '0.000', '0.000', '0.000', '0.000', 
'StringIO.py:38(_complain_ifclosed)'],
-                    ['2', '0.000', '0.000', '0.000', '0.000', '{isinstance}'],
-                    ['2', '0.000', '0.000', '0.000', '0.000', '{len}'],
-                    ['2', '0.000', '0.000', '0.000', '0.000', "{method 
'append' of 'list' objects}"],
-                    ['1', '0.000', '0.000', '0.000', '0.000', "{method 
'disable' of '_lsprof.Profiler' objects}"]
-                ]
-
-            self.assertListEqual(actual, expected)
\ No newline at end of file
+            expected = [
+                ['ncalls', 'tottime', 'percall', 'cumtime', 'percall', 
'filename:lineno(function)'],
+                ['1', '0.000', '0.000', '0.000', '0.000', 
'<string>:1(<module>)'],
+                ['1', '0.000', '0.000', '0.000', '0.000', '{built-in method 
builtins.exec}'],
+                ['1', '0.000', '0.000', '0.000', '0.000', '{built-in method 
builtins.print}'],
+                ['1', '0.000', '0.000', '0.000', '0.000', "{method 'disable' 
of '_lsprof.Profiler' objects}"]
+            ]
+            self.assertListEqual(actual, expected)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/project/tests/test_sensitive_data_in_request.py 
new/django-silk-4.0.0/project/tests/test_sensitive_data_in_request.py
--- old/django-silk-3.0.4/project/tests/test_sensitive_data_in_request.py       
2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/project/tests/test_sensitive_data_in_request.py       
2020-01-21 09:09:29.000000000 +0100
@@ -11,6 +11,76 @@
 HTTP_CONTENT_TYPE = 'Content-Type'
 
 
+class MaskCredentialsInFormsTest(TestCase):
+    def _mask(self, value):
+        return RequestModelFactory(None)._mask_credentials(value)
+
+    def test_mask_credentials_preserves_single_insensitive_values(self):
+        self.assertIn("public", self._mask("foo=public"))
+
+    def 
test_mask_credentials_preserves_insensitive_values_between_sensitive_values(self):
+        self.assertIn("public", self._mask("password=1&foo=public&secret=2"))
+
+    def test_mask_credentials_masks_sensitive_values(self):
+        self.assertNotIn("secret", self._mask("password=secret"))
+
+    def 
test_mask_credentials_masks_sensitive_values_between_insensitive_values(self):
+        self.assertNotIn("secret", 
self._mask("public1=foo&password=secret&public2=bar"))
+
+    def test_mask_credentials_is_case_insensitive(self):
+        self.assertNotIn("secret", self._mask("UsErNaMe=secret"))
+
+    def test_mask_credentials_handles_prefixes(self):
+        self.assertNotIn("secret", self._mask("prefixed-username=secret"))
+
+    def test_mask_credentials_handles_suffixes(self):
+        self.assertNotIn("secret", self._mask("username-with-suffix=secret"))
+
+    def test_mask_credentials_handles_complex_cases(self):
+        self.assertNotIn("secret", 
self._mask("foo=public&prefixed-uSeRname-with-suffix=secret&bar=public"))
+
+
+class MaskCredentialsInJsonTest(TestCase):
+    def _mask(self, value):
+        return RequestModelFactory(None)._mask_credentials(json.dumps(value))
+
+    def test_mask_credentials_preserves_single_insensitive_values(self):
+        self.assertIn("public", self._mask({"foo": "public"}))
+
+    def 
test_mask_credentials_preserves_insensitive_values_in_presence_of_sensitive(self):
+        self.assertIn("public", self._mask({"password": "secret", "foo": 
"public"}))
+
+    def test_mask_credentials_masks_sensitive_values(self):
+        self.assertNotIn("secret", self._mask({"password": "secret"}))
+
+    def 
test_mask_credentials_masks_sensitive_values_in_presence_of_regular(self):
+        self.assertNotIn("secret", self._mask({"foo": "public", "password": 
"secret"}))
+
+    def test_mask_credentials_is_case_insensitive(self):
+        self.assertNotIn("secret", self._mask({"UsErNaMe": "secret"}))
+
+    def test_mask_credentials_handles_prefixes(self):
+        self.assertNotIn("secret", self._mask({"prefixed-username": "secret"}))
+
+    def test_mask_credentials_handles_suffixes(self):
+        self.assertNotIn("secret", self._mask({"username-with-suffix": 
"secret"}))
+
+    def test_mask_credentials_handles_complex_cases(self):
+        self.assertNotIn("secret", self._mask({
+            "foo": "public",
+            "prefixed-uSeRname-with-suffix": "secret"
+        }))
+
+    def test_mask_credentials_in_nested_data_structures(self):
+        self.assertNotIn("secret", self._mask({
+            "foo": "public",
+            "nested": {
+                "prefixed-uSeRname-with-suffix": "secret",
+            },
+        }))
+
+
+
 class TestEncodingForRequests(TestCase):
     """
     Check that the RequestModelFactory masks sensitive data
@@ -33,7 +103,8 @@
     def test_password_in_json(self):
         mock_request = Mock()
         mock_request.META = {DJANGO_META_CONTENT_TYPE: 'application/json; 
charset=UTF-8'}
-        d = {'x': 'testunmasked', 'username': 'test_username', 'password': 
'testpassword'}
+        d = {'x': 'testunmasked', 'username': 'test_username', 'password': 
'testpassword',
+             'prefixed-secret': 'testsecret'}
         mock_request.body = json.dumps(d)
         mock_request.get = mock_request.META.get
         factory = RequestModelFactory(mock_request)
@@ -41,12 +112,15 @@
         self.assertIn('testunmasked', raw_body)
         self.assertNotIn('test_username', raw_body)
         self.assertNotIn('testpassword', raw_body)
+        self.assertNotIn('testsecret', raw_body)
         self.assertNotIn('test_username', body)
         self.assertNotIn('testpassword', body)
+        self.assertNotIn('testsecret', body)
 
         for datum in [json.loads(body), json.loads(raw_body)]:
             self.assertEqual(datum['username'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
             self.assertEqual(datum['password'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
+            self.assertEqual(datum['prefixed-secret'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
             self.assertEqual(datum['x'], 'testunmasked')
 
     def test_password_in_batched_json(self):
@@ -73,3 +147,15 @@
                 self.assertEqual(datum['username'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
                 self.assertEqual(datum['password'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
                 self.assertEqual(datum['x'], 'testunmasked')
+
+    def test_authorization_header(self):
+        mock_request = Mock()
+        mock_request.META = {'HTTP_AUTHORIZATION': 'secret'}
+        mock_request.body = ''
+        mock_request.get = mock_request.META.get
+        factory = RequestModelFactory(mock_request)
+        headers = factory.encoded_headers()
+        json_headers = json.loads(headers)
+        
+        self.assertIn('AUTHORIZATION', json_headers)
+        self.assertEqual(json_headers['AUTHORIZATION'], 
RequestModelFactory.CLEANSED_SUBSTITUTE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/requirements.txt 
new/django-silk-4.0.0/requirements.txt
--- old/django-silk-3.0.4/requirements.txt      2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/requirements.txt      2020-01-21 09:09:29.000000000 
+0100
@@ -7,7 +7,7 @@
 pytz>2014.2
 mock>=1.0.1
 Pillow>=3.2
-Django>=1.11
+Django>=2.2
 freezegun>=0.3
 factory-boy>=2.8.1
 gprof2dot>=2017.09.19
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/setup.py 
new/django-silk-4.0.0/setup.py
--- old/django-silk-3.0.4/setup.py      2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/setup.py      2020-01-21 09:09:29.000000000 +0100
@@ -3,25 +3,14 @@
 import os
 from setuptools import setup
 
-try:
-    from pypandoc import convert
-
-    def read_md(f):
-        return convert(f, 'rst')
-except ImportError:
-    print("warning: pypandoc module not found, could not convert Markdown to 
RST")
-
-    def read_md(f):
-        return open(f, 'r').read()
-
-README = read_md('README.md')
-
 # allow setup.py to be run from any path
 os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
 
+README = open('README.md', 'rb').read().decode("UTF-8")
+
 setup(
     name='django-silk',
-    version='3.0.4',
+    version='4.0.0',
     packages=['silk'],
     include_package_data=True,
     license='MIT License',
@@ -35,25 +24,20 @@
         'Development Status :: 5 - Production/Stable',
         'Environment :: Web Environment',
         'Framework :: Django',
-        'Framework :: Django :: 1.11',
-        'Framework :: Django :: 2.0',
-        'Framework :: Django :: 2.1',
         'Framework :: Django :: 2.2',
+        'Framework :: Django :: 3.0',
         'Intended Audience :: Developers',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
         'Topic :: Internet :: WWW/HTTP',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
     ],
     install_requires=[
-        'Django>=1.11',
+        'Django>=2.2',
         'Pygments',
         'python-dateutil',
         'requests',
@@ -62,5 +46,6 @@
         'autopep8',
         'pytz',
         'gprof2dot>=2017.09.19',
-    ]
+    ],
+    python_requires='>=3.5'
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/auth.py 
new/django-silk-4.0.0/silk/auth.py
--- old/django-silk-3.0.4/silk/auth.py  2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/auth.py  2020-01-21 09:09:29.000000000 +0100
@@ -1,8 +1,7 @@
-from functools import wraps
+from functools import wraps, WRAPPER_ASSIGNMENTS
 
 from django.contrib.auth.decorators import login_required
 from django.core.exceptions import PermissionDenied
-from django.utils.decorators import available_attrs
 
 from silk.config import SilkyConfig
 
@@ -26,7 +25,7 @@
 
 def user_passes_test(test_func):
     def decorator(view_func):
-        @wraps(view_func, assigned=available_attrs(view_func))
+        @wraps(view_func, assigned=WRAPPER_ASSIGNMENTS)
         def _wrapped_view(request, *args, **kwargs):
             if test_func(request.user):
                 return view_func(request, *args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/code_generation/curl.py 
new/django-silk-4.0.0/silk/code_generation/curl.py
--- old/django-silk-3.0.4/silk/code_generation/curl.py  2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/code_generation/curl.py  2020-01-21 
09:09:29.000000000 +0100
@@ -1,7 +1,7 @@
 import json
 
 # noinspection PyUnresolvedReferences
-from django.utils.six.moves.urllib.parse import urlencode
+from urllib.parse import urlencode
 
 import jinja2
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/silk/code_generation/django_test_client.py 
new/django-silk-4.0.0/silk/code_generation/django_test_client.py
--- old/django-silk-3.0.4/silk/code_generation/django_test_client.py    
2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/code_generation/django_test_client.py    
2020-01-21 09:09:29.000000000 +0100
@@ -2,7 +2,7 @@
 
 import jinja2
 # noinspection PyUnresolvedReferences
-from django.utils.six.moves.urllib.parse import urlencode
+from urllib.parse import urlencode
 from silk.profiling.dynamic import is_str_typ
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/collector.py 
new/django-silk-4.0.0/silk/collector.py
--- old/django-silk-3.0.4/silk/collector.py     2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/silk/collector.py     2020-01-21 09:09:29.000000000 
+0100
@@ -4,7 +4,7 @@
 import pstats
 import logging
 
-from django.utils.six import StringIO, with_metaclass
+from io import StringIO
 
 from silk import models
 from silk.config import SilkyConfig
@@ -26,7 +26,7 @@
         'these methods, Silk will not have the chance to inspect the 
request/response objects.')
 
 
-class DataCollector(with_metaclass(Singleton, object)):
+class DataCollector(metaclass=Singleton):
     """
     Provides the ability to save all models at the end of the request. We
     cannot save during the request due to the possibility of atomic blocks
@@ -92,7 +92,12 @@
         self.request = request
         self._configure()
 
-        if silky_config.SILKY_PYTHON_PROFILER:
+        if silky_config.SILKY_PYTHON_PROFILER_FUNC:
+            should_profile = silky_config.SILKY_PYTHON_PROFILER_FUNC(request)
+        else:
+            should_profile = silky_config.SILKY_PYTHON_PROFILER
+
+        if should_profile:
             self.local.pythonprofiler = cProfile.Profile()
             self.local.pythonprofiler.enable()
 
@@ -154,10 +159,20 @@
                 self.request.prof_file = f.name
                 self.request.save()
 
-        for _, query in self.queries.items():
-            query_model = models.SQLQuery.objects.create(**query)
-            query['model'] = query_model
-        for _, profile in self.profiles.items():
+        sql_queries = []
+        for identifier, query in self.queries.items():
+            query['identifier'] = identifier
+            sql_query = models.SQLQuery(**query)
+            sql_queries += [sql_query]
+
+        models.SQLQuery.objects.bulk_create(sql_queries)
+        sql_queries = models.SQLQuery.objects.filter(request=self.request)
+        for sql_query in sql_queries.all():
+            query = self.queries.get(sql_query.identifier)
+            if query:
+                query['model'] = sql_query
+
+        for profile in self.profiles.values():
             profile_query_models = []
             if TYP_QUERIES in profile:
                 profile_queries = profile[TYP_QUERIES]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/config.py 
new/django-silk-4.0.0/silk/config.py
--- old/django-silk-3.0.4/silk/config.py        2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/silk/config.py        2020-01-21 09:09:29.000000000 
+0100
@@ -1,7 +1,5 @@
 from copy import copy
 
-from django.utils import six
-
 from silk.singleton import Singleton
 
 
@@ -11,7 +9,7 @@
     return False
 
 
-class SilkyConfig(six.with_metaclass(Singleton, object)):
+class SilkyConfig(metaclass=Singleton):
     defaults = {
         'SILKY_DYNAMIC_PROFILING': [],
         'SILKY_IGNORE_PATHS': [],
@@ -28,6 +26,7 @@
         'SILKY_INTERCEPT_PERCENT': 100,
         'SILKY_INTERCEPT_FUNC': None,
         'SILKY_PYTHON_PROFILER': False,
+        'SILKY_PYTHON_PROFILER_FUNC': None,
         'SILKY_STORAGE_CLASS': 'silk.storage.ProfilerResultStorage',
         'SILKY_MIDDLEWARE_CLASS': 'silk.middleware.SilkyMiddleware'
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/silk/migrations/0007_sqlquery_identifier.py 
new/django-silk-4.0.0/silk/migrations/0007_sqlquery_identifier.py
--- old/django-silk-3.0.4/silk/migrations/0007_sqlquery_identifier.py   
1970-01-01 01:00:00.000000000 +0100
+++ new/django-silk-4.0.0/silk/migrations/0007_sqlquery_identifier.py   
2020-01-21 09:09:29.000000000 +0100
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.6 on 2019-10-26 12:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('silk', '0006_fix_request_prof_file_blank'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='sqlquery',
+            name='identifier',
+            field=models.IntegerField(default=-1),
+        ),
+    ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/model_factory.py 
new/django-silk-4.0.0/silk/model_factory.py
--- old/django-silk-3.0.4/silk/model_factory.py 2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/silk/model_factory.py 2020-01-21 09:09:29.000000000 
+0100
@@ -74,12 +74,18 @@
         to the name. So, for example, a header called X-Bender would be mapped 
to the META key HTTP_X_BENDER."
         """
         headers = {}
+        sensitive_headers = {'AUTHORIZATION'}
+
         for k, v in self.request.META.items():
             if k.startswith('HTTP') or k in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
                 splt = k.split('_')
                 if splt[0] == 'HTTP':
                     splt = splt[1:]
                 k = '-'.join(splt)
+
+                if k in sensitive_headers:
+                    v = RequestModelFactory.CLEANSED_SUBSTITUTE
+
                 headers[k] = v
         if SilkyConfig().SILKY_HIDE_COOKIES:
             try:
@@ -97,14 +103,17 @@
         key_string = '|'.join(sensitive_keys)
 
         def replace_pattern_values(obj):
+            pattern = re.compile(key_string, re.I)
             if isinstance(obj, dict):
-                for key in set(obj.keys()) & sensitive_keys:
-                    obj[key] = RequestModelFactory.CLEANSED_SUBSTITUTE
+                for key in obj.keys():
+                    if pattern.search(key):
+                        obj[key] = RequestModelFactory.CLEANSED_SUBSTITUTE
+                    else:
+                        obj[key] = replace_pattern_values(obj[key])
             elif isinstance(obj, list):
                 for index, item in enumerate(obj):
                     obj[index] = replace_pattern_values(item)
             else:
-                pattern = re.compile(r'{}'.format(key_string), re.I)
                 if pattern.search(str(obj)):
                     return RequestModelFactory.CLEANSED_SUBSTITUTE
             return obj
@@ -112,7 +121,7 @@
         try:
             json_body = json.loads(body)
         except Exception as e:
-            pattern = re.compile(r'({})=(.*?)(&|$)'.format(key_string), re.M)
+            pattern = re.compile(r'({})[^=]*=(.*?)(&|$)'.format(key_string), 
re.M | re.I)
             try:
                 results = re.findall(pattern, body)
             except Exception:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/models.py 
new/django-silk-4.0.0/silk/models.py
--- old/django-silk-3.0.4/silk/models.py        2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/silk/models.py        2020-01-21 09:09:29.000000000 
+0100
@@ -216,6 +216,7 @@
 
 # TODO rewrite docstring
 class SQLQueryManager(models.Manager):
+    @transaction.atomic
     def bulk_create(self, *args, **kwargs):
         """ensure that num_sql_queries remains consistent. Bulk create does 
not call
         the model save() method and hence we must add this logic here too"""
@@ -223,18 +224,10 @@
             objs = args[0]
         else:
             objs = kwargs.get('objs')
+        for obj in objs:
+            obj.prepare_save()
 
-        with transaction.atomic():
-            request_counter = Counter([x.request_id for x in objs])
-            requests = Request.objects.filter(pk__in=request_counter.keys())
-            # TODO: Not that there is ever more than one request (but there 
could be eventually)
-            # but perhaps there is a cleaner way of apply the increment from 
the counter without iterating
-            # and saving individually? e.g. bulk update but with diff. 
increments. Couldn't come up with this
-            # off hand.
-            for r in requests:
-                r.num_sql_queries = F('num_sql_queries') + 
request_counter[r.pk]
-                r.save()
-            return super(SQLQueryManager, self).bulk_create(*args, **kwargs)
+        return super(SQLQueryManager, self).bulk_create(*args, **kwargs)
 
 
 class SQLQuery(models.Model):
@@ -242,6 +235,7 @@
     start_time = DateTimeField(null=True, blank=True, default=timezone.now)
     end_time = DateTimeField(null=True, blank=True)
     time_taken = FloatField(blank=True, null=True)
+    identifier = IntegerField(default=-1)
     request = ForeignKey(
         Request, related_name='queries', null=True,
         blank=True, db_index=True, on_delete=models.CASCADE,
@@ -289,9 +283,7 @@
                     pass
         return tables
 
-    @transaction.atomic()
-    def save(self, *args, **kwargs):
-
+    def prepare_save(self):
         if self.end_time and self.start_time:
             interval = self.end_time - self.start_time
             self.time_taken = interval.total_seconds() * 1000
@@ -301,6 +293,9 @@
                 self.request.num_sql_queries += 1
                 self.request.save(update_fields=['num_sql_queries'])
 
+    @transaction.atomic()
+    def save(self, *args, **kwargs):
+        self.prepare_save()
         super(SQLQuery, self).save(*args, **kwargs)
 
     @transaction.atomic()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/profiling/dynamic.py 
new/django-silk-4.0.0/silk/profiling/dynamic.py
--- old/django-silk-3.0.4/silk/profiling/dynamic.py     2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/profiling/dynamic.py     2020-01-21 
09:09:29.000000000 +0100
@@ -4,8 +4,6 @@
 import sys
 import re
 
-from django.utils import six
-
 from silk.profiling.profiler import silk_profile
 
 Logger = logging.getLogger('silk.profiling.dynamic')
@@ -53,7 +51,7 @@
     @param module: module object or module name in form 'path.to.module'
     @param func: function object or function name in form 'foo' or 
'Class.method'
     """
-    if isinstance(module, six.string_types) or isinstance(module, 
six.text_type):
+    if isinstance(module, str):
         module = _get_module(module)
     decorator = silk_profile(name, _dynamic=True)
     func_name = func
@@ -144,12 +142,12 @@
     # could be.
     #
     # relevant: 
http://stackoverflow.com/questions/2749655/why-are-closures-broken-within-exec
-    globals = six.get_function_globals(func)
+    globals = func.__globals__
     locals = calling_frame.f_locals
     combined = globals.copy()
     combined.update(locals)
     Logger.debug('New src_str:\n %s' % src_str)
-    six.exec_(src_str, combined, context)
+    exec(src_str, combined, context)
     return context[func.__name__]
 
 
@@ -199,8 +197,7 @@
 
 
 def is_str_typ(o):
-    return any(map(partial(isinstance, o), six.string_types)) \
-        or isinstance(o, six.text_type)
+    return isinstance(o, str)
 
 
 def inject_context_manager_func(module, func, start_line, end_line, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/profiling/profiler.py 
new/django-silk-4.0.0/silk/profiling/profiler.py
--- old/django-silk-3.0.4/silk/profiling/profiler.py    2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/profiling/profiler.py    2020-01-21 
09:09:29.000000000 +0100
@@ -6,8 +6,6 @@
 from django.conf import settings
 from django.utils import timezone
 
-from django.utils import six
-
 from silk.collector import DataCollector
 from silk.config import SilkyConfig
 from silk.models import _time_taken
@@ -138,7 +136,7 @@
             def wrapped_target(*args, **kwargs):
                 with silk_meta_profiler():
                     try:
-                        func_code = six.get_function_code(target)
+                        func_code = target.__code__
                     except AttributeError:
                         raise NotImplementedError('Profile not implemented to 
decorate type %s' % target.__class__.__name__)
                     line_num = func_code.co_firstlineno
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/singleton.py 
new/django-silk-4.0.0/silk/singleton.py
--- old/django-silk-3.0.4/silk/singleton.py     2019-09-05 18:47:21.000000000 
+0200
+++ new/django-silk-4.0.0/silk/singleton.py     2020-01-21 09:09:29.000000000 
+0100
@@ -1,7 +1,7 @@
 __author__ = 'mtford'
 
 
-class Singleton(type):
+class Singleton(type, metaclass=object):
     def __init__(cls, name, bases, d):
         super(Singleton, cls).__init__(name, bases, d)
         cls.instance = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/templates/silk/clear_db.html 
new/django-silk-4.0.0/silk/templates/silk/clear_db.html
--- old/django-silk-3.0.4/silk/templates/silk/clear_db.html     1970-01-01 
01:00:00.000000000 +0100
+++ new/django-silk-4.0.0/silk/templates/silk/clear_db.html     2020-01-21 
09:09:29.000000000 +0100
@@ -0,0 +1,96 @@
+{% extends 'silk/base/root_base.html' %}
+{% load static %}
+{% load silk_inclusion %}
+
+{% block menu %}
+    {% if silk_request %}
+        {% request_menu request silk_request %}
+    {% else %}
+        {% root_menu request %}
+    {% endif %}
+{% endblock %}
+
+{% block style %}
+    {{ block.super }}
+    <style>
+        .container {
+            padding: 0 1em;
+        }
+
+        h2 {
+            margin-bottom: 10px;
+        }
+
+        .cleardb-form .cleardb-form-wrapper{
+            margin-bottom: 20px;
+        }
+
+        .cleardb-form label {
+            display: block;
+            margin-bottom: 8px;
+        }
+
+        .cleardb-form .btn {
+            background: #333344;
+            color: #fff;
+            padding: 10px 20px;
+            border-radius: 2px;
+            cursor: pointer;
+            box-shadow: none;
+            font-size: 16px;
+            line-height: 20px;
+            border: 0;
+            min-width: 150px;
+            text-align: center;
+        }
+        .cleardb-form label :last-child {
+            margin-bottom: 0;
+        }
+        .msg {
+            margin-top: 20px;
+            color: #bac54b;
+        }
+    </style>
+
+{% endblock %}
+
+{% block js %}
+    {{ block.super }}
+    <script>
+
+        $(document).ready(function () {
+            initFilters();
+            initFilterButton();
+        });
+    </script>
+{% endblock %}
+
+
+{% block data %}
+    <div class="container">
+        <h2>Silk Clear DB</h2>
+        <form class="cleardb-form" action="." method="post">
+            {% csrf_token %}
+            <div class="cleardb-form-wrapper">
+                <label>
+                    <input type="checkbox" name="clear_requests" 
disabled="disabled"/>
+                    Requests
+                </label>
+                <label>
+                    <input type="checkbox" name="clear_profiling" 
disabled="disabled"/>
+                    Profiling
+                </label>
+                <label>
+                    <input type="checkbox" name="clear_all"/>
+                    All
+                </label>
+            </div>
+            <button class="btn">Clear</button>
+        </form>
+        <div class="msg">{{ msg }}</div>
+    </div>
+{% endblock %}
+
+
+{% block filter %}{% endblock %}
+{% block filters %}{% endblock %}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-silk-3.0.4/silk/templates/silk/inclusion/root_menu.html 
new/django-silk-4.0.0/silk/templates/silk/inclusion/root_menu.html
--- old/django-silk-3.0.4/silk/templates/silk/inclusion/root_menu.html  
2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/templates/silk/inclusion/root_menu.html  
2020-01-21 09:09:29.000000000 +0100
@@ -20,4 +20,11 @@
         </div>
     </a>
 </div>
+<div class="menu-item selectable-menu-item {% navactive request 'silk:cleardb' 
%}">
+    <a href="{% url "silk:cleardb" %}">
+        <div class="menu-item-outer">
+            <div class="menu-item-inner">Clear DB</div>
+        </div>
+    </a>
+</div>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/urls.py 
new/django-silk-4.0.0/silk/urls.py
--- old/django-silk-3.0.4/silk/urls.py  2019-09-05 18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/urls.py  2020-01-21 09:09:29.000000000 +0100
@@ -1,5 +1,6 @@
 from django.conf.urls import url
 
+from silk.views.clear_db import ClearDBView
 from silk.views.profile_detail import ProfilingDetailView
 from silk.views.profile_download import ProfileDownloadView
 from silk.views.profile_dot import ProfileDotView
@@ -82,6 +83,7 @@
         name='profile_sql_detail'
     ),
     url(r'^profiling/$', ProfilingView.as_view(), name='profiling'),
+    url(r'^cleardb/$', ClearDBView.as_view(), name='cleardb'),
     url(
         r'^request/(?P<request_id>[a-zA-Z0-9\-]+)/cprofile/$',
         CProfileView.as_view(),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/utils/profile_parser.py 
new/django-silk-4.0.0/silk/utils/profile_parser.py
--- old/django-silk-3.0.4/silk/utils/profile_parser.py  2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/utils/profile_parser.py  2020-01-21 
09:09:29.000000000 +0100
@@ -1,4 +1,3 @@
-from six import text_type
 import re
 
 
@@ -9,7 +8,7 @@
     """
     Parse the output of cProfile to a list of tuples.
     """
-    if isinstance(output, text_type):
+    if isinstance(output, str):
         output = output.split('\n')
     for i, line in enumerate(output):
         # ignore n function calls, total time and ordered by and empty lines
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/views/clear_db.py 
new/django-silk-4.0.0/silk/views/clear_db.py
--- old/django-silk-3.0.4/silk/views/clear_db.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/django-silk-4.0.0/silk/views/clear_db.py        2020-01-21 
09:09:29.000000000 +0100
@@ -0,0 +1,33 @@
+from django.db import connection
+from django.shortcuts import render
+from django.utils.decorators import method_decorator
+from django.views.generic import View
+
+from silk.auth import login_possibly_required, permissions_possibly_required
+from silk.models import Request, Response, SQLQuery, Profile
+
+
+class ClearDBView(View):
+
+    def _truncate_tables(self, models):
+        raw_query = 'TRUNCATE TABLE {0};'
+        truncate_query = [raw_query.format(m._meta.db_table) for m in models]
+        truncate_query = ' '.join(truncate_query)
+        query = 'SET FOREIGN_KEY_CHECKS = 0; {0} SET FOREIGN_KEY_CHECKS = 
1;'.format(truncate_query)
+        cursor = connection.cursor()
+        cursor.execute(query)
+
+    @method_decorator(login_possibly_required)
+    @method_decorator(permissions_possibly_required)
+    def get(self, request, *_, **kwargs):
+        return render(request, 'silk/clear_db.html')
+
+    @method_decorator(login_possibly_required)
+    @method_decorator(permissions_possibly_required)
+    def post(self, request, *_, **kwargs):
+        context = {}
+        if 'clear_all' in request.POST:
+            self._truncate_tables([Response, SQLQuery, Profile, Request])
+            tables = ['Response', 'SQLQuery', 'Profile', 'Request']
+            context['msg'] = 'Cleared data for following silk tables: 
{0}'.format(', '.join(tables))
+        return render(request, 'silk/clear_db.html', context=context)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-silk-3.0.4/silk/views/profile_dot.py 
new/django-silk-4.0.0/silk/views/profile_dot.py
--- old/django-silk-3.0.4/silk/views/profile_dot.py     2019-09-05 
18:47:21.000000000 +0200
+++ new/django-silk-4.0.0/silk/views/profile_dot.py     2020-01-21 
09:09:29.000000000 +0100
@@ -5,7 +5,7 @@
 import shutil
 from contextlib import closing, contextmanager
 # 3rd party
-from six import StringIO
+from io import StringIO
 from django.shortcuts import get_object_or_404
 from django.utils.decorators import method_decorator
 from django.views.generic import View


Reply via email to