diff --git a/jupyter_server/base/handlers.py b/jupyter_server/base/handlers.py index 35d2ec7136..0d8ba29b1e 100755 --- a/jupyter_server/base/handlers.py +++ b/jupyter_server/base/handlers.py @@ -575,7 +575,11 @@ def content_security_policy(self): def update_api_activity(self): """Update last_activity of API requests""" # record activity of authenticated requests - if self._track_activity and getattr(self, '_user_cache', None): + if ( + self._track_activity + and getattr(self, '_user_cache', None) + and self.get_argument('no_track_activity', None) is None + ): self.settings['api_last_activity'] = utcnow() def finish(self, *args, **kwargs): diff --git a/jupyter_server/services/api/tests/test_api.py b/jupyter_server/services/api/tests/test_api.py index 76e089d3c6..be8310ba3c 100644 --- a/jupyter_server/services/api/tests/test_api.py +++ b/jupyter_server/services/api/tests/test_api.py @@ -1,8 +1,8 @@ """Test the basic /api endpoints""" -import requests +from datetime import timedelta -from jupyter_server._tz import isoformat +from jupyter_server._tz import isoformat, utcnow from jupyter_server.utils import url_path_join from jupyter_server.tests.launchserver import ServerTestBase @@ -30,3 +30,18 @@ def test_get_status(self): assert data['last_activity'].endswith('Z') assert data['started'].endswith('Z') assert data['started'] == isoformat(self.server.web_app.settings['started']) + + def test_no_track_activity(self): + # initialize with old last api activity + old = utcnow() - timedelta(days=1) + settings = self.server.web_app.settings + settings['api_last_activity'] = old + # accessing status doesn't update activity + self.get('status') + assert settings['api_last_activity'] == old + # accessing with ?no_track_activity doesn't update activity + self.get('contents?no_track_activity=1') + assert settings['api_last_activity'] == old + # accessing without ?no_track_activity does update activity + self.get('contents') + assert settings['api_last_activity'] > old diff --git a/jupyter_server/services/contents/manager.py b/jupyter_server/services/contents/manager.py index db1738f3ae..28ac63fcce 100644 --- a/jupyter_server/services/contents/manager.py +++ b/jupyter_server/services/contents/manager.py @@ -331,7 +331,10 @@ def increment_filename(self, filename, path='', insert=''): """ # Extract the full suffix from the filename (e.g. .tar.gz) path = path.strip('/') - basename, dot, ext = filename.partition('.') + basename, dot, ext = filename.rpartition('.') + if ext != 'ipynb': + basename, dot, ext = filename.partition('.') + suffix = dot + ext for i in itertools.count(): @@ -425,6 +428,8 @@ def copy(self, from_path, to_path=None): If to_path not specified, it will be the parent directory of from_path. If to_path is a directory, filename will increment `from_path-Copy#.ext`. + Considering multi-part extensions, the Copy# part will be placed before the first dot for all the extensions except `ipynb`. + For easier manual searching in case of notebooks, the Copy# part will be placed before the last dot. from_path must be a full path to a file. """ diff --git a/jupyter_server/services/kernels/kernelmanager.py b/jupyter_server/services/kernels/kernelmanager.py index f63a231081..b63f3f35ae 100644 --- a/jupyter_server/services/kernels/kernelmanager.py +++ b/jupyter_server/services/kernels/kernelmanager.py @@ -296,7 +296,6 @@ def shutdown_kernel(self, kernel_id, now=False): kernel._activity_stream = None self.stop_buffering(kernel_id) self._kernel_connections.pop(kernel_id, None) - self.last_kernel_activity = utcnow() # Decrease the metric of number of kernels # running for the relevant kernel type by 1