Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-jupyter-server-fileid for 
openSUSE:Factory checked in at 2023-04-24 22:31:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jupyter-server-fileid (Old)
 and      /work/SRC/openSUSE:Factory/.python-jupyter-server-fileid.new.1533 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-jupyter-server-fileid"

Mon Apr 24 22:31:01 2023 rev:2 rq:1082311 version:0.9.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-jupyter-server-fileid/python-jupyter-server-fileid.changes
        2023-03-24 15:20:45.726994630 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-jupyter-server-fileid.new.1533/python-jupyter-server-fileid.changes
      2023-04-24 22:31:04.779462994 +0200
@@ -1,0 +2,16 @@
+Sun Apr 23 17:38:40 UTC 2023 - Ben Greiner <[email protected]>
+
+- Update to 0.9.0
+  * add Jupyter Releaser workflows #65 (@dlqqq)
+  * Fix behavior for OOB move followed by IB move #63 (@dlqqq)
+- Release 0.8.0
+  * Add db_journal_mode trait to FileIdManager classes #61
+    (@kevin-bates)
+- Release 0.7.0
+  * remove mtime fallback #47 (@dlqqq)
+  * Make ArbitraryFileIdManager filesystem-agnostic and fix Windows
+    CI #46 (@kevin-bates)
+  * Relax jupyter_events dependency requirement #57 (@akchinSTC)
+  * Update check-jsonschema usage to latest style #50 (@sirosen)
+
+-------------------------------------------------------------------

Old:
----
  jupyter_server_fileid-0.6.0.tar.gz

New:
----
  jupyter_server_fileid-0.9.0.tar.gz

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

Other differences:
------------------
++++++ python-jupyter-server-fileid.spec ++++++
--- /var/tmp/diff_new_pack.0xGB44/_old  2023-04-24 22:31:05.359466441 +0200
+++ /var/tmp/diff_new_pack.0xGB44/_new  2023-04-24 22:31:05.359466441 +0200
@@ -17,14 +17,15 @@
 
 
 %define plainpython3dist python3dist
-%define distversion 0.6
+%define pyversion 0.9.0
+%define distversion 0.9
 %if 0%{?suse_version} > 1500
 %bcond_without libalternatives
 %else
 %bcond_with libalternatives
 %endif
 Name:           python-jupyter-server-fileid
-Version:        0.6.0
+Version:        %{pyversion}
 Release:        0
 Summary:        File IDs for documents in a running Jupyter Server
 License:        BSD-3-Clause
@@ -36,9 +37,9 @@
 BuildRequires:  fdupes
 BuildRequires:  jupyter-rpm-macros
 BuildRequires:  python-rpm-macros
-Requires:       (python-jupyter-events >= 0.5.0 with python-jupyter-events < 1)
-Requires:       (python-jupyter-server >= 1.15 with python-jupyter-server < 3)
 Requires:       jupyter-server-fileid = %{version}
+Requires:       python-jupyter-events >= 0.5.0
+Requires:       (python-jupyter-server >= 1.15 with python-jupyter-server < 3)
 Recommends:     python-click
 Provides:       python-jupyter_server_fileid = %{version}-%{release}
 BuildArch:      noarch
@@ -47,10 +48,10 @@
 Requires:       alts
 %else
 Requires(post): update-alternatives
-Requires(postun): update-alternatives
+Requires(postun):update-alternatives
 %endif
 # SECTION test requirements
-BuildRequires:  %{python_module jupyter-events >= 0.5.0 with 
%python-jupyter-events < 1}
+BuildRequires:  %{python_module jupyter-events >= 0.5.0}
 BuildRequires:  %{python_module jupyter-server-test >= 1.15 with 
%python-jupyter-server-test < 3}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module traitlets}
@@ -83,7 +84,9 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%pytest
+# flaky on obs
+donttest="test_get_path_oob_move_nested"
+%pytest -k "not ($donttest)"
 
 %pre
 %python_libalternatives_reset_alternative jupyter-fileid

++++++ jupyter_server_fileid-0.6.0.tar.gz -> jupyter_server_fileid-0.9.0.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/.github/workflows/prep-release.yml 
new/jupyter_server_fileid-0.9.0/.github/workflows/prep-release.yml
--- old/jupyter_server_fileid-0.6.0/.github/workflows/prep-release.yml  
1970-01-01 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/.github/workflows/prep-release.yml  
2020-02-02 01:00:00.000000000 +0100
@@ -0,0 +1,41 @@
+name: "Step 1: Prep Release"
+on:
+  workflow_dispatch:
+    inputs:
+      version_spec:
+        description: "New Version Specifier"
+        default: "next"
+        required: false
+      branch:
+        description: "The branch to target"
+        required: false
+      post_version_spec:
+        description: "Post Version Specifier"
+        required: false
+      since:
+        description: "Use PRs with activity since this date or git reference"
+        required: false
+      since_last_stable:
+        description: "Use PRs with activity since the last stable git tag"
+        required: false
+        type: boolean
+jobs:
+  prep_release:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
+
+      - name: Prep Release
+        id: prep-release
+        uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
+        with:
+          token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
+          version_spec: ${{ github.event.inputs.version_spec }}
+          post_version_spec: ${{ github.event.inputs.post_version_spec }}
+          branch: ${{ github.event.inputs.branch }}
+          since: ${{ github.event.inputs.since }}
+          since_last_stable: ${{ github.event.inputs.since_last_stable }}
+
+      - name: "** Next Step **"
+        run: |
+          echo "Optional): Review Draft Release: ${{ 
steps.prep-release.outputs.release_url }}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/.github/workflows/publish-release.yml 
new/jupyter_server_fileid-0.9.0/.github/workflows/publish-release.yml
--- old/jupyter_server_fileid-0.6.0/.github/workflows/publish-release.yml       
1970-01-01 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/.github/workflows/publish-release.yml       
2020-02-02 01:00:00.000000000 +0100
@@ -0,0 +1,52 @@
+name: "Step 2: Publish Release"
+on:
+  workflow_dispatch:
+    inputs:
+      branch:
+        description: "The target branch"
+        required: false
+      release_url:
+        description: "The URL of the draft GitHub release"
+        required: false
+      steps_to_skip:
+        description: "Comma separated list of steps to skip"
+        required: false
+
+jobs:
+  publish_release:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
+
+      - name: Populate Release
+        id: populate-release
+        uses: 
jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
+        with:
+          token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
+          branch: ${{ github.event.inputs.branch }}
+          release_url: ${{ github.event.inputs.release_url }}
+          steps_to_skip: ${{ github.event.inputs.steps_to_skip }}
+
+      - name: Finalize Release
+        id: finalize-release
+        env:
+          PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
+          PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }}
+          TWINE_USERNAME: __token__
+          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+        uses: 
jupyter-server/jupyter-releaser/.github/actions/finalize-release@v2
+        with:
+          token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
+          release_url: ${{ steps.populate-release.outputs.release_url }}
+
+      - name: "** Next Step **"
+        if: ${{ success() }}
+        run: |
+          echo "Verify the final release"
+          echo ${{ steps.finalize-release.outputs.release_url }}
+
+      - name: "** Failure Message **"
+        if: ${{ failure() }}
+        run: |
+          echo "Failed to Publish the Draft Release Url:"
+          echo ${{ steps.populate-release.outputs.release_url }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/.github/workflows/test-python.yml 
new/jupyter_server_fileid-0.9.0/.github/workflows/test-python.yml
--- old/jupyter_server_fileid-0.6.0/.github/workflows/test-python.yml   
2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/.github/workflows/test-python.yml   
2020-02-02 01:00:00.000000000 +0100
@@ -19,12 +19,12 @@
       matrix:
         os:
           - ubuntu-latest
-          # - windows-latest
+          - windows-latest
           - macos-latest
         python-version: ["3.7", "3.10"]
         include:
-          # - os: windows-latest
-          #   python-version: "3.9"
+          - os: windows-latest
+            python-version: "3.9"
           # - os: ubuntu-latest
           #   python-version: "pypy-3.8"
           - os: macos-latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jupyter_server_fileid-0.6.0/.pre-commit-config.yaml 
new/jupyter_server_fileid-0.9.0/.pre-commit-config.yaml
--- old/jupyter_server_fileid-0.6.0/.pre-commit-config.yaml     2020-02-02 
01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/.pre-commit-config.yaml     2020-02-02 
01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.3.0
+    rev: v4.4.0
     hooks:
       - id: end-of-file-fixer
       - id: check-case-conflict
@@ -16,43 +16,39 @@
       - id: trailing-whitespace
 
   - repo: https://github.com/psf/black
-    rev: 22.10.0
+    rev: 23.1.0
     hooks:
       - id: black
 
   - repo: https://github.com/PyCQA/isort
-    rev: 5.10.1
+    rev: 5.12.0
     hooks:
       - id: isort
         args: ["--profile", "black"]
         files: \.py$
 
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v0.982
+    rev: v1.0.0
     hooks:
       - id: mypy
         additional_dependencies: [types-requests]
 
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.1.0
+    rev: v3.3.1
     hooks:
       - id: pyupgrade
         args: [--py37-plus]
 
   - repo: https://github.com/john-hen/Flake8-pyproject
-    rev: 1.1.0.post0
+    rev: 1.2.2
     hooks:
       - id: Flake8-pyproject
         alias: flake8
         additional_dependencies:
           ["flake8-bugbear==22.6.22", "flake8-implicit-str-concat==0.2.0"]
 
-  - repo: https://github.com/sirosen/check-jsonschema
-    rev: 0.18.4
+  - repo: https://github.com/python-jsonschema/check-jsonschema
+    rev: 0.21.0
     hooks:
-      - id: check-jsonschema
-        name: "Check GitHub Workflows"
-        files: ^\.github/workflows/
-        types: [yaml]
-        args: ["--schemafile", "https://json.schemastore.org/github-workflow";]
+      - id: check-github-workflows
         stages: [manual]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jupyter_server_fileid-0.6.0/CHANGELOG.md 
new/jupyter_server_fileid-0.9.0/CHANGELOG.md
--- old/jupyter_server_fileid-0.6.0/CHANGELOG.md        2020-02-02 
01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/CHANGELOG.md        2020-02-02 
01:00:00.000000000 +0100
@@ -2,6 +2,64 @@
 
 <!-- <START NEW CHANGELOG ENTRY> -->
 
+## 0.9.0
+
+([Full 
Changelog](https://github.com/jupyter-server/jupyter_server_fileid/compare/v0.8.0...505806162b4df60b4cbb461cfec1266b81df32ce))
+
+### Enhancements made
+
+- add Jupyter Releaser workflows 
[#65](https://github.com/jupyter-server/jupyter_server_fileid/pull/65) 
([@dlqqq](https://github.com/dlqqq))
+- Fix behavior for OOB move followed by IB move 
[#63](https://github.com/jupyter-server/jupyter_server_fileid/pull/63) 
([@dlqqq](https://github.com/dlqqq))
+
+### Contributors to this release
+
+([GitHub contributors page for this 
release](https://github.com/jupyter-server/jupyter_server_fileid/graphs/contributors?from=2023-02-23&to=2023-04-09&type=c))
+
+[@dleen](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Adleen+updated%3A2023-02-23..2023-04-09&type=Issues)
 | 
[@dlqqq](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Adlqqq+updated%3A2023-02-23..2023-04-09&type=Issues)
+
+<!-- <END NEW CHANGELOG ENTRY> -->
+
+## 0.8.0
+
+([Full 
Changelog](https://github.com/jupyter-server/jupyter_server_fileid/compare/v0.7.0...542ccebfcf7713a81a4f2fbd07e8227573c3a282))
+
+### Enhancements made
+
+- Add db_journal_mode trait to FileIdManager classes 
[#61](https://github.com/jupyter-server/jupyter_server_fileid/pull/61) 
([@kevin-bates](https://github.com/kevin-bates))
+
+### Contributors to this release
+
+([GitHub contributors page for this 
release](https://github.com/jupyter-server/jupyter_server_fileid/graphs/contributors?from=2023-02-16&to=2023-02-23&type=c))
+
+[@codecov](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Acodecov+updated%3A2023-02-16..2023-02-23&type=Issues)
 | 
[@kevin-bates](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Akevin-bates+updated%3A2023-02-16..2023-02-23&type=Issues)
+
+## 0.7.0
+
+([Full 
Changelog](https://github.com/jupyter-server/jupyter_server_fileid/compare/v0.6.0...f42d481b072f8c1a961ad8dc6c2b3ab35a6d0777))
+
+### Enhancements made
+
+- remove mtime fallback 
[#47](https://github.com/jupyter-server/jupyter_server_fileid/pull/47) 
([@dlqqq](https://github.com/dlqqq))
+- Make ArbitraryFileIdManager filesystem-agnostic and fix Windows CI 
[#46](https://github.com/jupyter-server/jupyter_server_fileid/pull/46) 
([@kevin-bates](https://github.com/kevin-bates))
+
+### Bugs fixed
+
+- Relax jupyter_events dependency requirement 
[#57](https://github.com/jupyter-server/jupyter_server_fileid/pull/57) 
([@akchinSTC](https://github.com/akchinSTC))
+- Fix project URL 
[#55](https://github.com/jupyter-server/jupyter_server_fileid/pull/55) 
([@frenzymadness](https://github.com/frenzymadness))
+- Make ArbitraryFileIdManager filesystem-agnostic and fix Windows CI 
[#46](https://github.com/jupyter-server/jupyter_server_fileid/pull/46) 
([@kevin-bates](https://github.com/kevin-bates))
+
+### Maintenance and upkeep improvements
+
+### Other merged PRs
+
+- Update check-jsonschema usage to latest style 
[#50](https://github.com/jupyter-server/jupyter_server_fileid/pull/50) 
([@sirosen](https://github.com/sirosen))
+
+### Contributors to this release
+
+([GitHub contributors page for this 
release](https://github.com/jupyter-server/jupyter_server_fileid/graphs/contributors?from=2022-10-28&to=2023-02-16&type=c))
+
+[@akchinSTC](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3AakchinSTC+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@codecov](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Acodecov+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@codecov-commenter](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Acodecov-commenter+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@dlqqq](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Adlqqq+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@frenzymadness](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Afrenzymadness+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@kevin-bates](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Akevin-bates+updated%3A2022-10-28..2023-02-16&type=Issues)
 | [@pre-commit-ci](https://github.com/search?q=
 
repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Apre-commit-ci+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@sirosen](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Asirosen+updated%3A2022-10-28..2023-02-16&type=Issues)
 | 
[@welcome](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Awelcome+updated%3A2022-10-28..2023-02-16&type=Issues)
+
 ## 0.6.0
 
 ([Full 
Changelog](https://github.com/jupyter-server/jupyter_server_fileid/compare/v0.5.0...328d893ff2323f20925e036e57eb62f302fa94e2))
@@ -22,8 +80,6 @@
 
 
[@codecov-commenter](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Acodecov-commenter+updated%3A2022-10-25..2022-10-28&type=Issues)
 | 
[@dlqqq](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Adlqqq+updated%3A2022-10-25..2022-10-28&type=Issues)
 | 
[@kevin-bates](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Akevin-bates+updated%3A2022-10-25..2022-10-28&type=Issues)
 | 
[@welcome](https://github.com/search?q=repo%3Ajupyter-server%2Fjupyter_server_fileid+involves%3Awelcome+updated%3A2022-10-25..2022-10-28&type=Issues)
 
-<!-- <END NEW CHANGELOG ENTRY> -->
-
 ## 0.5.0
 
 ([Full 
Changelog](https://github.com/jupyter-server/jupyter_server_fileid/compare/v0.4.2...d968097b42f7b4d21fd851bd69c23a34098e675a))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jupyter_server_fileid-0.6.0/PKG-INFO 
new/jupyter_server_fileid-0.9.0/PKG-INFO
--- old/jupyter_server_fileid-0.6.0/PKG-INFO    2020-02-02 01:00:00.000000000 
+0100
+++ new/jupyter_server_fileid-0.9.0/PKG-INFO    2020-02-02 01:00:00.000000000 
+0100
@@ -1,7 +1,7 @@
 Metadata-Version: 2.1
 Name: jupyter_server_fileid
-Version: 0.6.0
-Project-URL: Home, https://github.com/github_username/jupyter_server_fileid
+Version: 0.9.0
+Project-URL: Home, https://github.com/jupyter-server/jupyter_server_fileid
 Author-email: "David L. Qiu" <[email protected]>
 License: BSD 3-Clause License
         
@@ -43,7 +43,7 @@
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Requires-Python: >=3.7
-Requires-Dist: jupyter-events~=0.5.0
+Requires-Dist: jupyter-events>=0.5.0
 Requires-Dist: jupyter-server<3,>=1.15
 Provides-Extra: cli
 Requires-Dist: click; extra == 'cli'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/__init__.py 
new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/__init__.py
--- old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/__init__.py   
2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/__init__.py   
2020-02-02 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 """A Jupyter Server extension providing an implementation of the File ID 
service."""
 from .extension import FileIdExtension
 
-__version__ = "0.6.0"
+__version__ = "0.9.0"
 
 
 def _jupyter_server_extension_points():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/extension.py 
new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/extension.py
--- old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/extension.py  
2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/extension.py  
2020-02-02 01:00:00.000000000 +0100
@@ -6,7 +6,6 @@
 
 
 class FileIdExtension(ExtensionApp):
-
     name = "jupyter_server_fileid"
 
     file_id_manager_class = Type(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/manager.py 
new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/manager.py
--- old/jupyter_server_fileid-0.6.0/jupyter_server_fileid/manager.py    
2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/jupyter_server_fileid/manager.py    
2020-02-02 01:00:00.000000000 +0100
@@ -1,4 +1,5 @@
 import os
+import posixpath
 import sqlite3
 import stat
 import time
@@ -7,7 +8,7 @@
 from typing import Any, Callable, Dict, Optional
 
 from jupyter_core.paths import jupyter_data_dir
-from traitlets import TraitError, Unicode, validate
+from traitlets import TraitError, Unicode, default, validate
 from traitlets.config.configurable import LoggingConfigurable
 
 
@@ -74,67 +75,71 @@
             )
         return proposal["value"]
 
+    JOURNAL_MODES = ["DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"]
+    db_journal_mode = Unicode(
+        help=(
+            f"The journal mode setting for the SQLite database.  Must be one 
of {JOURNAL_MODES}."
+        ),
+        config=True,
+    )
+
+    @validate("db_journal_mode")
+    def _validate_db_journal_mode(self, proposal):
+        candidate_value = proposal["value"]
+        if candidate_value is None or candidate_value.upper() not in 
self.JOURNAL_MODES:
+            raise TraitError(
+                f"db_journal_mode ('{candidate_value}') must be one of 
{self.JOURNAL_MODES}."
+            )
+        return candidate_value.upper()
+
     @staticmethod
     def _uuid() -> str:
         return str(uuid.uuid4())
 
+    @abstractmethod
     def _normalize_path(self, path: str) -> str:
-        """Accepts an API path and returns a filesystem path, i.e. one prefixed
-        by root_dir and uses os.path.sep."""
-        # use commonprefix instead of commonpath, since root_dir may not be a
-        # absolute POSIX path.
-        if os.path.commonprefix([self.root_dir, path]) != self.root_dir:
-            path = os.path.join(self.root_dir, path)
-
-        return path
+        """Accepts an API path and returns a "persistable" path, i.e. one 
prefixed
+        by root_dir that can then be persisted in a format relative to the 
implementation."""
+        pass
 
+    @abstractmethod
     def _from_normalized_path(self, path: Optional[str]) -> Optional[str]:
-        """Accepts a filesystem path and returns an API path, i.e. one relative
+        """Accepts a "persistable" path and returns an API path, i.e. one 
relative
         to root_dir and uses forward slashes as the path separator. Returns
         `None` if the given path is None or is not relative to root_dir."""
-        if path is None:
-            return None
-
-        if os.path.commonprefix([self.root_dir, path]) != self.root_dir:
-            return None
-
-        relpath = os.path.relpath(path, self.root_dir)
-        # always use forward slashes to delimit children
-        relpath = relpath.replace(os.path.sep, "/")
-
-        return relpath
+        pass
 
-    def _move_recursive(self, old_path: str, new_path: str, sep: str = 
os.path.sep) -> None:
+    def _move_recursive(self, old_path: str, new_path: str, path_mgr: Any = 
os.path) -> None:
         """Move all children of a given directory at `old_path` to a new
         directory at `new_path`, delimited by `sep`."""
-        old_path_glob = old_path + sep + "*"
+        old_path_glob = old_path + path_mgr.sep + "*"
         records = self.con.execute(
             "SELECT id, path FROM Files WHERE path GLOB ?", (old_path_glob,)
         ).fetchall()
 
         for record in records:
             id, old_recpath = record
-            new_recpath = os.path.join(new_path, os.path.relpath(old_recpath, 
start=old_path))
+            new_recpath = path_mgr.join(new_path, 
path_mgr.relpath(old_recpath, start=old_path))
             self.con.execute("UPDATE Files SET path = ? WHERE id = ?", 
(new_recpath, id))
 
-    def _copy_recursive(self, from_path: str, to_path: str, sep: str = 
os.path.sep) -> None:
+    def _copy_recursive(self, from_path: str, to_path: str, path_mgr: Any = 
os.path) -> None:
         """Copy all children of a given directory at `from_path` to a new
         directory at `to_path`, delimited by `sep`."""
-        from_path_glob = from_path + sep + "*"
+        from_path_glob = from_path + path_mgr.sep + "*"
         records = self.con.execute(
             "SELECT path FROM Files WHERE path GLOB ?", (from_path_glob,)
         ).fetchall()
 
         for record in records:
             (from_recpath,) = record
-            to_recpath = os.path.join(to_path, os.path.relpath(from_recpath, 
start=from_path))
+            to_recpath = path_mgr.join(to_path, path_mgr.relpath(from_recpath, 
start=from_path))
             self.con.execute(
                 "INSERT INTO Files (id, path) VALUES (?, ?)", (self._uuid(), 
to_recpath)
             )
 
-    def _delete_recursive(self, path: str, sep: str = os.path.sep) -> None:
+    def _delete_recursive(self, path: str, path_mgr: Any = os.path) -> None:
         """Delete all children of a given directory, delimited by `sep`."""
-        path_glob = path + sep + "*"
+        path_glob = path + path_mgr.sep + "*"
         self.con.execute("DELETE FROM Files WHERE path GLOB ?", (path_glob,))
 
     @abstractmethod
@@ -232,6 +237,19 @@
     Server 2.
     """
 
+    @validate("root_dir")
+    def _validate_root_dir(self, proposal):
+        # Convert root_dir to an api path, since that's essentially what we 
persist.
+        if proposal["value"] is None:
+            return ""
+
+        normalized_content_root = self._normalize_separators(proposal["value"])
+        return normalized_content_root
+
+    @default("db_journal_mode")
+    def _default_db_journal_mode(self):
+        return "DELETE"
+
     def __init__(self, *args, **kwargs):
         # pass args and kwargs to parent Configurable
         super().__init__(*args, **kwargs)
@@ -242,9 +260,11 @@
         self.log.info(f"ArbitraryFileIdManager : Configured database path: 
{self.db_path}")
         self.con = sqlite3.connect(self.db_path)
         self.log.info("ArbitraryFileIdManager : Successfully connected to 
database file.")
-        self.log.info("ArbitraryFileIdManager : Creating File ID tables and 
indices.")
-        # do not allow reads to block writes. required when using multiple 
processes
-        self.con.execute("PRAGMA journal_mode = WAL")
+        self.log.info(
+            f"ArbitraryFileIdManager : Creating File ID tables and indices 
with "
+            f"journal_mode = {self.db_journal_mode}"
+        )
+        self.con.execute(f"PRAGMA journal_mode = {self.db_journal_mode}")
         self.con.execute(
             "CREATE TABLE IF NOT EXISTS Files("
             "id TEXT PRIMARY KEY NOT NULL, "
@@ -254,6 +274,41 @@
         self.con.execute("CREATE INDEX IF NOT EXISTS ix_Files_path ON Files 
(path)")
         self.con.commit()
 
+    @staticmethod
+    def _normalize_separators(path):
+        """Replaces backslashes with forward slashes, removing adjacent 
slashes."""
+
+        parts = path.strip("\\").split("\\")
+        return "/".join(parts)
+
+    def _normalize_path(self, path):
+        """Accepts an API path and returns a "persistable" path, i.e. one 
prefixed
+        by root_dir that can then be persisted in a format relative to the 
implementation."""
+        # use commonprefix instead of commonpath, since root_dir may not be a
+        # absolute POSIX path.
+
+        # norm_root_dir = self._normalize_separators(self.root_dir)
+        path = self._normalize_separators(path)
+        if posixpath.commonprefix([self.root_dir, path]) != self.root_dir:
+            path = posixpath.join(self.root_dir, path)
+
+        return path
+
+    def _from_normalized_path(self, path: Optional[str]) -> Optional[str]:
+        """Accepts a "persistable" path and returns an API path, i.e. one 
relative
+        to root_dir and uses forward slashes as the path separator. Returns
+        `None` if the given path is None or is not relative to root_dir."""
+        if path is None:
+            return None
+
+        # Convert root_dir to an api path, since that's essentially what we 
persist.
+        # norm_root_dir = self._normalize_separators(self.root_dir)
+        if posixpath.commonprefix([self.root_dir, path]) != self.root_dir:
+            return None
+
+        relpath = posixpath.relpath(path, self.root_dir)
+        return relpath
+
     def _create(self, path: str) -> str:
         path = self._normalize_path(path)
         id = self._uuid()
@@ -291,7 +346,7 @@
 
         if id:
             self.con.execute("UPDATE Files SET path = ? WHERE path = ?", 
(new_path, old_path))
-            self._move_recursive(old_path, new_path, "/")
+            self._move_recursive(old_path, new_path, posixpath)
         else:
             id = self._create(new_path)
 
@@ -303,7 +358,7 @@
         to_path = self._normalize_path(to_path)
 
         id = self._create(to_path)
-        self._copy_recursive(from_path, to_path, "/")
+        self._copy_recursive(from_path, to_path, posixpath)
 
         self.con.commit()
         return id
@@ -312,7 +367,7 @@
         path = self._normalize_path(path)
 
         self.con.execute("DELETE FROM Files WHERE path = ?", (path,))
-        self._delete_recursive(path, "/")
+        self._delete_recursive(path, posixpath)
 
         self.con.commit()
 
@@ -362,6 +417,10 @@
             )
         return proposal["value"]
 
+    @default("db_journal_mode")
+    def _default_db_journal_mode(self):
+        return "WAL"
+
     def __init__(self, *args, **kwargs):
         # pass args and kwargs to parent Configurable
         super().__init__(*args, **kwargs)
@@ -373,9 +432,11 @@
         self.log.info(f"LocalFileIdManager : Configured database path: 
{self.db_path}")
         self.con = sqlite3.connect(self.db_path)
         self.log.info("LocalFileIdManager : Successfully connected to database 
file.")
-        self.log.info("LocalFileIdManager : Creating File ID tables and 
indices.")
-        # do not allow reads to block writes. required when using multiple 
processes
-        self.con.execute("PRAGMA journal_mode = WAL")
+        self.log.info(
+            f"LocalFileIdManager : Creating File ID tables and indices with "
+            f"journal_mode = {self.db_journal_mode}"
+        )
+        self.con.execute(f"PRAGMA journal_mode = {self.db_journal_mode}")
         self.con.execute(
             "CREATE TABLE IF NOT EXISTS Files("
             "id TEXT PRIMARY KEY NOT NULL, "
@@ -395,12 +456,32 @@
         self.con.commit()
 
     def _normalize_path(self, path):
-        path = super()._normalize_path(path)
+        """Accepts an API path and returns a filesystem path, i.e. one 
prefixed by root_dir."""
+        if os.path.commonprefix([self.root_dir, path]) != self.root_dir:
+            path = os.path.join(self.root_dir, path)
+
         path = os.path.normcase(path)
         path = os.path.normpath(path)
-
         return path
 
+    def _from_normalized_path(self, path: Optional[str]) -> Optional[str]:
+        """Accepts a "persisted" filesystem path and returns an API path, i.e.
+        one relative to root_dir and uses forward slashes as the path 
separator.
+        Returns `None` if the given path is None or is not relative to 
root_dir.
+        """
+        if path is None:
+            return None
+
+        norm_root_dir = os.path.normcase(self.root_dir)
+        if os.path.commonprefix([norm_root_dir, path]) != norm_root_dir:
+            return None
+
+        relpath = os.path.relpath(path, norm_root_dir)
+        # always use forward slashes to delimit children
+        relpath = relpath.replace(os.path.sep, "/")
+
+        return relpath
+
     def _index_all(self):
         """Recursively indexes all directories under the server root."""
         self._index_dir_recursively(self.root_dir, self._stat(self.root_dir))
@@ -495,23 +576,6 @@
 
         scan_iter.close()
 
-    def _check_timestamps(self, stat_info):
-        """Returns True if the timestamps of a file match those recorded in the
-        Files table. Returns False otherwise."""
-
-        src = self.con.execute(
-            "SELECT crtime, mtime FROM Files WHERE ino = ?", (stat_info.ino,)
-        ).fetchone()
-
-        # if no record with matching ino, then return None
-        if not src:
-            return False
-
-        src_crtime, src_mtime = src
-        src_timestamp = src_crtime if src_crtime is not None else src_mtime
-        dst_timestamp = stat_info.crtime if stat_info.crtime is not None else 
stat_info.mtime
-        return src_timestamp == dst_timestamp
-
     def _sync_file(self, path, stat_info):
         """
         Syncs the file at `path` with the Files table by detecting whether the
@@ -545,16 +609,16 @@
             return None
 
         src = self.con.execute(
-            "SELECT id, path FROM Files WHERE ino = ?", (stat_info.ino,)
+            "SELECT id, path, crtime FROM Files WHERE ino = ?", 
(stat_info.ino,)
         ).fetchone()
 
         # if ino is not in database, return None
         if src is None:
             return None
-        id, old_path = src
+        id, old_path, crtime = src
 
         # if timestamps don't match, delete existing record and return None
-        if not self._check_timestamps(stat_info):
+        if crtime != stat_info.crtime:
             self.con.execute("DELETE FROM Files WHERE id = ?", (id,))
             return None
 
@@ -699,38 +763,29 @@
         prior to calling `get_path()`.
         """
         # optimistic approach: first check to see if path was not yet moved
-        row = self.con.execute("SELECT path, ino FROM Files WHERE id = ?", 
(id,)).fetchone()
-
-        # if file ID does not exist, return None
-        if not row:
-            return None
-
-        path, ino = row
-        stat_info = self._stat(path)
-
-        if stat_info and ino == stat_info.ino and 
self._check_timestamps(stat_info):
-            # if file already exists at path and the ino and timestamps match,
-            # then return the correct path immediately (best case)
-            return self._from_normalized_path(path)
-
-        # otherwise, try again after calling _sync_all() to sync the Files 
table to the file tree
-        self._sync_all()
-        row = self.con.execute("SELECT path, ino FROM Files WHERE id = ?", 
(id,)).fetchone()
-        # file ID already guaranteed to exist from previous check
-        path, ino = row
+        for retry in [True, False]:
+            row = self.con.execute(
+                "SELECT path, ino, crtime FROM Files WHERE id = ?", (id,)
+            ).fetchone()
+
+            # if file ID does not exist, return None
+            if not row:
+                return None
 
-        # if file no longer exists at path, return None
-        stat_info = self._stat(path)
-        if stat_info is None:
-            return None
+            path, ino, crtime = row
+            stat_info = self._stat(path)
 
-        # if inode numbers or timestamps of the file and record don't match,
-        # return None
-        if ino != stat_info.ino or not self._check_timestamps(stat_info):
-            return None
+            if stat_info and ino == stat_info.ino and crtime == 
stat_info.crtime:
+                # if file already exists at path and the ino and timestamps 
match,
+                # then return the correct path immediately (best case)
+                return self._from_normalized_path(path)
+
+            # otherwise, try again after calling _sync_all() to sync the Files 
table to the file tree
+            if retry:
+                self._sync_all()
 
-        # finally, convert the path to a relative one and return it
-        return self._from_normalized_path(path)
+        # If we're here, the retry didn't work.
+        return None
 
     @log(
         lambda self, old_path, new_path: f"Updating index following move from 
{old_path} to {new_path}.",
@@ -747,23 +802,18 @@
         if stat_info is None:
             return None
 
-        if stat_info.is_dir:
-            self._move_recursive(old_path, new_path)
-
-        # attempt to fetch ID associated with old path
-        # we avoid using get_id() here since that will always return None as 
file no longer exists at old path
-        row = self.con.execute("SELECT id FROM Files WHERE path = ?", 
(old_path,)).fetchone()
-        if row is None:
+        # sync the file and see if it was already indexed
+        #
+        # originally this method did not call _sync_file() for performance
+        # reasons, but this is needed to handle an edge case:
+        # https://github.com/jupyter-server/jupyter_server_fileid/issues/62
+        id = self._sync_file(new_path, stat_info)
+        if id is None:
             # if no existing record, create a new one
             id = self._create(new_path, stat_info)
-            self.con.commit()
-            return id
-        else:
-            # update existing record with new path and stat info
-            id = row[0]
-            self._update(id, stat_info, new_path)
-            self.con.commit()
-            return id
+
+        self.con.commit()
+        return id
 
     def _copy_recursive(self, from_path: str, to_path: str, _: str = "") -> 
None:
         """Copy all children of a given directory at `from_path` to a new
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jupyter_server_fileid-0.6.0/pyproject.toml 
new/jupyter_server_fileid-0.9.0/pyproject.toml
--- old/jupyter_server_fileid-0.6.0/pyproject.toml      2020-02-02 
01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/pyproject.toml      2020-02-02 
01:00:00.000000000 +0100
@@ -19,7 +19,10 @@
     "Programming Language :: Python :: 3.10",
     "Framework :: Jupyter",
 ]
-dependencies = ["jupyter_server>=1.15, <3", "jupyter_events~=0.5.0"]
+dependencies = [
+    "jupyter_server>=1.15, <3",
+    "jupyter_events>=0.5.0"
+]
 
 [project.optional-dependencies]
 test = [
@@ -39,7 +42,7 @@
 file="LICENSE"
 
 [project.urls]
-Home = "https://github.com/github_username/jupyter_server_fileid";
+Home = "https://github.com/jupyter-server/jupyter_server_fileid";
 
 [tool.hatch.build.targets.wheel.shared-data]
 "jupyter-config" = "etc/jupyter"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jupyter_server_fileid-0.6.0/tests/test_manager.py 
new/jupyter_server_fileid-0.9.0/tests/test_manager.py
--- old/jupyter_server_fileid-0.6.0/tests/test_manager.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/jupyter_server_fileid-0.9.0/tests/test_manager.py       2020-02-02 
01:00:00.000000000 +0100
@@ -1,11 +1,17 @@
 import ntpath
 import os
+import posixpath
+import sys
 from unittest.mock import patch
 
 import pytest
 from traitlets import TraitError
 
-from jupyter_server_fileid.manager import ArbitraryFileIdManager, 
LocalFileIdManager
+from jupyter_server_fileid.manager import (
+    ArbitraryFileIdManager,
+    BaseFileIdManager,
+    LocalFileIdManager,
+)
 
 
 @pytest.fixture
@@ -19,7 +25,8 @@
 def test_path_child(test_path, fs_helpers):
     path = os.path.join(test_path, "child")
     fs_helpers.touch(path)
-    return path
+    # return api-style path
+    return posixpath.join(test_path, "child")
 
 
 @pytest.fixture
@@ -34,14 +41,16 @@
 def old_path_child(old_path, fs_helpers):
     path = os.path.join(old_path, "child")
     fs_helpers.touch(path, dir=True)
-    return path
+    # return api-style path
+    return posixpath.join(old_path, "child")
 
 
 @pytest.fixture
 def old_path_grandchild(old_path_child, fs_helpers):
     path = os.path.join(old_path_child, "grandchild")
     fs_helpers.touch(path)
-    return path
+    # return api-style path
+    return posixpath.join(old_path_child, "grandchild")
 
 
 @pytest.fixture
@@ -52,18 +61,43 @@
 
 @pytest.fixture
 def new_path_child(new_path):
-    return os.path.join(new_path, "child")
+    return posixpath.join(new_path, "child")
 
 
 @pytest.fixture
 def new_path_grandchild(new_path_child):
-    return os.path.join(new_path_child, "grandchild")
+    return posixpath.join(new_path_child, "grandchild")
 
 
-def get_id_nosync(fid_manager, path):
-    if not os.path.isabs(path):
+def _normalize_path_local(fid_manager, path):
+    if os.path.commonprefix([fid_manager.root_dir, path]) != 
fid_manager.root_dir:
         path = os.path.join(fid_manager.root_dir, path)
 
+    path = os.path.normcase(path)
+    path = os.path.normpath(path)
+    return path
+
+
+def _normalize_separators(path):
+    parts = path.strip("\\").split("\\")
+    return "/".join(parts)
+
+
+def _normalize_path_arbitrary(fid_manager, path):
+    if posixpath.commonprefix([fid_manager.root_dir, path]) != 
fid_manager.root_dir:
+        path = posixpath.join(fid_manager.root_dir, path)
+
+    path = _normalize_separators(path)
+    return path
+
+
+def get_id_nosync(fid_manager, path):
+    # We need to first put the path into a form the fileId manager 
implementation will for persistence.
+    if isinstance(fid_manager, LocalFileIdManager):
+        path = _normalize_path_local(fid_manager, path)
+    else:
+        path = _normalize_path_arbitrary(fid_manager, path)
+
     row = fid_manager.con.execute("SELECT id FROM Files WHERE path = ?", 
(path,)).fetchone()
     return row and row[0]
 
@@ -75,7 +109,25 @@
     if path is None:
         return None
 
-    return os.path.relpath(path, fid_manager.root_dir)
+    return os.path.relpath(path, os.path.normcase(fid_manager.root_dir))
+
+
+def normalize_path(fid_manager: BaseFileIdManager, path: str) -> str:
+    """Normalize path or case based on operating system and FileIdManager 
instance.
+
+    When testing instances of LocalFileIdManager, we need to normalize the
+    case relative to the OS when comparing results of get_path() since Windows
+    is case-insensitive.
+
+    When testing instances of ArbitraryFileIdManager, we need to normalize the
+    path, regardless of OS, when comparing results of get_path() since this 
fileID
+    manager must be filesystem agnostic.
+    """
+    if isinstance(fid_manager, LocalFileIdManager):
+        path = os.path.normcase(path)
+
+    parts = path.strip("\\").split("\\")
+    return "/".join(parts)
 
 
 def test_validates_root_dir(fid_db_path):
@@ -86,7 +138,7 @@
     afm = ArbitraryFileIdManager(root_dir=root_dir, db_path=fid_db_path)
     assert afm.root_dir == root_dir
     afm2 = ArbitraryFileIdManager(root_dir=None, db_path=fid_db_path)
-    assert afm2.root_dir is None
+    assert afm2.root_dir == ""
 
 
 def test_validates_db_path(jp_root_dir, any_fid_manager_class):
@@ -134,6 +186,10 @@
     assert id == any_fid_manager.index(test_path)
 
 
[email protected](
+    sys.version_info < (3, 8) and sys.platform.startswith("win"),
+    reason="symbolic links on Windows Python 3.7 not behaving like 3.8+",
+)
 def test_index_symlink(fid_manager, test_path):
     link_path = os.path.join(fid_manager.root_dir, "link_path")
     os.symlink(os.path.join(fid_manager.root_dir, test_path), link_path)
@@ -153,6 +209,10 @@
     assert fid_manager.index(new_path) == id
 
 
+crtime_support = os.name == "nt" or hasattr(os.stat_result, "st_birthtime")
+
+
[email protected](not crtime_support, reason="Requires crtime support.")
 def test_index_after_deleting_dir_in_same_path(fid_manager, test_path, 
fs_helpers):
     old_id = fid_manager.index(test_path)
 
@@ -165,6 +225,7 @@
     assert fid_manager.get_path(new_id) == test_path
 
 
[email protected](not crtime_support, reason="Requires crtime support.")
 def test_index_after_deleting_regfile_in_same_path(fid_manager, 
test_path_child, fs_helpers):
     old_id = fid_manager.index(test_path_child)
 
@@ -285,10 +346,6 @@
     assert path == arbitrary_fid_manager.get_path(id)
 
 
-@patch("os.path.sep", new="\\")
-@patch("os.path.relpath", new=ntpath.relpath)
-@patch("os.path.normpath", new=ntpath.normpath)
-@patch("os.path.join", new=ntpath.join)
 def test_get_path_returns_api_path(jp_root_dir, fid_db_path):
     """Tests whether get_path() method always returns an API path, i.e. one
     relative to the server root and one delimited by forward slashes (even if
@@ -369,7 +426,7 @@
     fs_helpers.move(old_path, new_path)
     fs_helpers.move(old_test_path, new_test_path)
 
-    assert fid_manager.get_path(id) == new_test_path
+    assert fid_manager.get_path(id) == normalize_path(fid_manager, 
new_test_path)
 
 
 # move file into directory within an indexed-but-moved directory
@@ -388,7 +445,7 @@
     fs_helpers.move(old_path, new_path)
     fs_helpers.move(old_test_path, new_test_path)
 
-    assert fid_manager.get_path(id) == new_test_path
+    assert fid_manager.get_path(id) == normalize_path(fid_manager, 
new_test_path)
 
 
 def test_move_unindexed(any_fid_manager, old_path, new_path, fs_helpers):
@@ -413,16 +470,38 @@
     assert any_fid_manager.get_path(old_id) == new_path
 
 
-# test for disjoint move handling
-# disjoint move: any out-of-band move that does not preserve stat info
-def test_disjoint_move_indexed(any_fid_manager, old_path, new_path, 
fs_helpers):
-    old_id = any_fid_manager.index(old_path)
+def test_oob_ib_move(fid_manager, test_path, fs_helpers):
+    """
+    Test an out-of-band move followed by an in-band move.
+    """
+    new_path_1 = "path1"
+    new_path_2 = "path2"
+    id = fid_manager.index(test_path)
 
-    fs_helpers.delete(old_path)
-    fs_helpers.touch(new_path, dir=True)
-    new_id = any_fid_manager.move(old_path, new_path)
+    # out-of-band
+    fs_helpers.move(test_path, new_path_1)
+    # in-band
+    fs_helpers.move(new_path_1, new_path_2)
+    fid_manager.move(new_path_1, new_path_2)
+
+    assert id == fid_manager.get_id(new_path_2)
 
-    assert old_id == new_id
+
+def test_ib_oob_move(fid_manager, test_path, fs_helpers):
+    """
+    Test an in-band move followed by an out-of-band move.
+    """
+    new_path_1 = "path1"
+    new_path_2 = "path2"
+    id = fid_manager.index(test_path)
+
+    # in-band
+    fs_helpers.move(test_path, new_path_1)
+    fid_manager.move(test_path, new_path_1)
+    # out-of-band
+    fs_helpers.move(new_path_1, new_path_2)
+
+    assert id == fid_manager.get_id(new_path_2)
 
 
 def test_move_recursive(
@@ -508,3 +587,29 @@
     any_fid_manager.save(test_path)
 
     assert any_fid_manager.get_id(test_path) == id
+
+
[email protected](
+    "db_journal_mode", ["invalid", None, "DELETE", "TRUNCATE", "PERSIST", 
"MEMORY", "WAL", "OFF"]
+)
+def test_db_journal_mode(any_fid_manager_class, fid_db_path, jp_root_dir, 
db_journal_mode):
+    if db_journal_mode == "invalid":  # test invalid
+        with pytest.raises(TraitError, match=" must be one of "):
+            any_fid_manager_class(
+                db_path=fid_db_path, root_dir=str(jp_root_dir), 
db_journal_mode=db_journal_mode
+            )
+    else:
+        if not db_journal_mode:  # test correct defaults
+            expected_journal_mode = (
+                "WAL" if any_fid_manager_class.__name__ == 
"LocalFileIdManager" else "DELETE"
+            )
+            fid_manager = any_fid_manager_class(db_path=fid_db_path, 
root_dir=str(jp_root_dir))
+        else:  # test any valid value
+            expected_journal_mode = db_journal_mode
+            fid_manager = any_fid_manager_class(
+                db_path=fid_db_path, root_dir=str(jp_root_dir), 
db_journal_mode=db_journal_mode
+            )
+
+        cursor = fid_manager.con.execute("PRAGMA journal_mode")
+        actual_journal_mode = cursor.fetchone()
+        assert actual_journal_mode[0].upper() == expected_journal_mode

Reply via email to