text: import os.path
  import sys
  import unittest.mock
  from textwrap import dedent
  
  import py
  
  import pytest
  from _pytest.pathlib import ensure_deletable
  from _pytest.pathlib import fnmatch_ex
  from _pytest.pathlib import get_extended_length_path_str
  from _pytest.pathlib import get_lock_path
  from _pytest.pathlib import import_path
  from _pytest.pathlib import ImportPathMismatchError
  from _pytest.pathlib import maybe_delete_a_numbered_dir
  from _pytest.pathlib import Path
  from _pytest.pathlib import resolve_package_path
  
  
  class TestFNMatcherPort:
      """Test that our port of py.common.FNMatcher (fnmatch_ex) produces the same results as the
      original py.path.local.fnmatch method.
      """
  
      @pytest.fixture(params=["pathlib", "py.path"])
      def match(self, request):
          if request.param == "py.path":
  
              def match_(pattern, path):
                  return py.path.local(path).fnmatch(pattern)
  
          else:
              assert request.param == "pathlib"
  
              def match_(pattern, path):
                  return fnmatch_ex(pattern, path)
  
          return match_
  
      if sys.platform == "win32":
          drv1 = "c:"
          drv2 = "d:"
      else:
          drv1 = "/c"
          drv2 = "/d"
  
      @pytest.mark.parametrize(
          "pattern, path",
          [
              ("*.py", "foo.py"),
              ("*.py", "bar/foo.py"),
              ("test_*.py", "foo/test_foo.py"),
              ("tests/*.py", "tests/foo.py"),
              (drv1 + "/*.py", drv1 + "/foo.py"),
              (drv1 + "/foo/*.py", drv1 + "/foo/foo.py"),
              ("tests/**/test*.py", "tests/foo/test_foo.py"),
              ("tests/**/doc/test*.py", "tests/foo/bar/doc/test_foo.py"),
              ("tests/**/doc/**/test*.py", "tests/foo/doc/bar/test_foo.py"),
          ],
      )
      def test_matching(self, match, pattern, path):
          assert match(pattern, path)
  
      def test_matching_abspath(self, match):
          abspath = os.path.abspath(os.path.join("tests/foo.py"))
          assert match("tests/foo.py", abspath)
  
      @pytest.mark.parametrize(
          "pattern, path",
          [
              ("*.py", "foo.pyc"),
              ("*.py", "foo/foo.pyc"),
              ("tests/*.py", "foo/foo.py"),
              (drv1 + "/*.py", drv2 + "/foo.py"),
              (drv1 + "/foo/*.py", drv2 + "/foo/foo.py"),
              ("tests/**/test*.py", "tests/foo.py"),
              ("tests/**/test*.py", "foo/test_foo.py"),
              ("tests/**/doc/test*.py", "tests/foo/bar/doc/foo.py"),
              ("tests/**/doc/test*.py", "tests/foo/bar/test_foo.py"),
          ],
      )
      def test_not_matching(self, match, pattern, path):
          assert not match(pattern, path)
  
  
  class TestImportPath:
      """
  
      Most of the tests here were copied from py lib's tests for "py.local.path.pyimport".
  
      Having our own pyimport-like function is inline with removing py.path dependency in the future.
      """
  
      @pytest.fixture(scope="session")
      def path1(self, tmpdir_factory):
          path = tmpdir_factory.mktemp("path")
          self.setuptestfs(path)
          yield path
          assert path.join("samplefile").check()
  
      def setuptestfs(self, path):
          # print "setting up test fs for", repr(path)
          samplefile = path.ensure("samplefile")
          samplefile.write("samplefile\n")
  
          execfile = path.ensure("execfile")
          execfile.write("x=42")
  
          execfilepy = path.ensure("execfile.py")
          execfilepy.write("x=42")
  
          d = {1: 2, "hello": "world", "answer": 42}
          path.ensure("samplepickle").dump(d)
  
          sampledir = path.ensure("sampledir", dir=1)
          sampledir.ensure("otherfile")
  
          otherdir = path.ensure("otherdir", dir=1)
          otherdir.ensure("__init__.py")
  
          module_a = otherdir.ensure("a.py")
          module_a.write("from .b import stuff as result\n")
          module_b = otherdir.ensure("b.py")
          module_b.write('stuff="got it"\n')
          module_c = otherdir.ensure("c.py")
          module_c.write(
              dedent(
                  """
              import py;
              import otherdir.a
              value = otherdir.a.result
          """
              )
          )
          module_d = otherdir.ensure("d.py")
          module_d.write(
              dedent(
                  """
              import py;
              from otherdir import a
              value2 = a.result
          """
              )
          )
  
      def test_smoke_test(self, path1):
          obj = import_path(path1.join("execfile.py"))
          assert obj.x == 42  # type: ignore[attr-defined]
          assert obj.__name__ == "execfile"
  
      def test_renamed_dir_creates_mismatch(self, tmpdir, monkeypatch):
          p = tmpdir.ensure("a", "test_x123.py")
          import_path(p)
          tmpdir.join("a").move(tmpdir.join("b"))
          with pytest.raises(ImportPathMismatchError):
              import_path(tmpdir.join("b", "test_x123.py"))
  
          # Errors can be ignored.
          monkeypatch.setenv("PY_IGNORE_IMPORTMISMATCH", "1")
          import_path(tmpdir.join("b", "test_x123.py"))
  
          # PY_IGNORE_IMPORTMISMATCH=0 does not ignore error.
          monkeypatch.setenv("PY_IGNORE_IMPORTMISMATCH", "0")
          with pytest.raises(ImportPathMismatchError):
              import_path(tmpdir.join("b", "test_x123.py"))
  
      def test_messy_name(self, tmpdir):
          # http://bitbucket.org/hpk42/py-trunk/issue/129
          path = tmpdir.ensure("foo__init__.py")
          module = import_path(path)
          assert module.__name__ == "foo__init__"
  
      def test_dir(self, tmpdir):
          p = tmpdir.join("hello_123")
          p_init = p.ensure("__init__.py")
          m = import_path(p)
          assert m.__name__ == "hello_123"
          m = import_path(p_init)
          assert m.__name__ == "hello_123"
  
      def test_a(self, path1):
          otherdir = path1.join("otherdir")
          mod = import_path(otherdir.join("a.py"))
          assert mod.result == "got it"  # type: ignore[attr-defined]
          assert mod.__name__ == "otherdir.a"
  
      def test_b(self, path1):
          otherdir = path1.join("otherdir")
          mod = import_path(otherdir.join("b.py"))
          assert mod.stuff == "got it"  # type: ignore[attr-defined]
          assert mod.__name__ == "otherdir.b"
  
      def test_c(self, path1):
          otherdir = path1.join("otherdir")
          mod = import_path(otherdir.join("c.py"))
          assert mod.value == "got it"  # type: ignore[attr-defined]
  
      def test_d(self, path1):
          otherdir = path1.join("otherdir")
          mod = import_path(otherdir.join("d.py"))
          assert mod.value2 == "got it"  # type: ignore[attr-defined]
  
      def test_import_after(self, tmpdir):
          tmpdir.ensure("xxxpackage", "__init__.py")
          mod1path = tmpdir.ensure("xxxpackage", "module1.py")
          mod1 = import_path(mod1path)
          assert mod1.__name__ == "xxxpackage.module1"
          from xxxpackage import module1
  
          assert module1 is mod1
  
      def test_check_filepath_consistency(self, monkeypatch, tmpdir):
          name = "pointsback123"
          ModuleType = type(os)
          p = tmpdir.ensure(name + ".py")
          for ending in (".pyc", ".pyo"):
              mod = ModuleType(name)
              pseudopath = tmpdir.ensure(name + ending)
              mod.__file__ = str(pseudopath)
              monkeypatch.setitem(sys.modules, name, mod)
              newmod = import_path(p)
              assert mod == newmod
          monkeypatch.undo()
          mod = ModuleType(name)
          pseudopath = tmpdir.ensure(name + "123.py")
          mod.__file__ = str(pseudopath)
          monkeypatch.setitem(sys.modules, name, mod)
          with pytest.raises(ImportPathMismatchError) as excinfo:
              import_path(p)
          modname, modfile, orig = excinfo.value.args
          assert modname == name
          assert modfile == pseudopath
          assert orig == p
          assert issubclass(ImportPathMismatchError, ImportError)
  
      def test_issue131_on__init__(self, tmpdir):
          # __init__.py files may be namespace packages, and thus the
          # __file__ of an imported module may not be ourselves
          # see issue
          p1 = tmpdir.ensure("proja", "__init__.py")
          p2 = tmpdir.ensure("sub", "proja", "__init__.py")
          m1 = import_path(p1)
          m2 = import_path(p2)
          assert m1 == m2
  
      def test_ensuresyspath_append(self, tmpdir):
          root1 = tmpdir.mkdir("root1")
          file1 = root1.ensure("x123.py")
          assert str(root1) not in sys.path
          import_path(file1, mode="append")
          assert str(root1) == sys.path[-1]
          assert str(root1) not in sys.path[:-1]
  
      def test_invalid_path(self, tmpdir):
          with pytest.raises(ImportError):
              import_path(tmpdir.join("invalid.py"))
  
      @pytest.fixture
      def simple_module(self, tmpdir):
          fn = tmpdir.join("mymod.py")
          fn.write(
              dedent(
                  """
              def foo(x): return 40 + x
              """
              )
          )
          return fn
  
      def test_importmode_importlib(self, simple_module):
          """importlib mode does not change sys.path"""
          module = import_path(simple_module, mode="importlib")
          assert module.foo(2) == 42  # type: ignore[attr-defined]
          assert simple_module.dirname not in sys.path
  
      def test_importmode_twice_is_different_module(self, simple_module):
          """importlib mode always returns a new module"""
          module1 = import_path(simple_module, mode="importlib")
          module2 = import_path(simple_module, mode="importlib")
          assert module1 is not module2
  
      def test_no_meta_path_found(self, simple_module, monkeypatch):
          """Even without any meta_path should still import module"""
          monkeypatch.setattr(sys, "meta_path", [])
          module = import_path(simple_module, mode="importlib")
          assert module.foo(2) == 42  # type: ignore[attr-defined]
  
          # mode='importlib' fails if no spec is found to load the module
          import importlib.util
  
          monkeypatch.setattr(
              importlib.util, "spec_from_file_location", lambda *args: None
          )
          with pytest.raises(ImportError):
              import_path(simple_module, mode="importlib")
  
  
  def test_resolve_package_path(tmp_path):
      pkg = tmp_path / "pkg1"
      pkg.mkdir()
      (pkg / "__init__.py").touch()
      (pkg / "subdir").mkdir()
      (pkg / "subdir/__init__.py").touch()
      assert resolve_package_path(pkg) == pkg
      assert resolve_package_path(pkg.joinpath("subdir", "__init__.py")) == pkg
  
  
  def test_package_unimportable(tmp_path):
      pkg = tmp_path / "pkg1-1"
      pkg.mkdir()
      pkg.joinpath("__init__.py").touch()
      subdir = pkg.joinpath("subdir")
      subdir.mkdir()
      pkg.joinpath("subdir/__init__.py").touch()
      assert resolve_package_path(subdir) == subdir
      xyz = subdir.joinpath("xyz.py")
      xyz.touch()
      assert resolve_package_path(xyz) == subdir
      assert not resolve_package_path(pkg)
  
  
  def test_access_denied_during_cleanup(tmp_path, monkeypatch):
      """Ensure that deleting a numbered dir does not fail because of OSErrors (#4262)."""
      path = tmp_path / "temp-1"
      path.mkdir()
  
      def renamed_failed(*args):
          raise OSError("access denied")
  
      monkeypatch.setattr(Path, "rename", renamed_failed)
  
      lock_path = get_lock_path(path)
      maybe_delete_a_numbered_dir(path)
      assert not lock_path.is_file()
  
  
  def test_long_path_during_cleanup(tmp_path):
      """Ensure that deleting long path works (particularly on Windows (#6775))."""
      path = (tmp_path / ("a" * 250)).resolve()
      if sys.platform == "win32":
          # make sure that the full path is > 260 characters without any
          # component being over 260 characters
          assert len(str(path)) > 260
          extended_path = "\\\\?\\" + str(path)
      else:
          extended_path = str(path)
      os.mkdir(extended_path)
      assert os.path.isdir(extended_path)
      maybe_delete_a_numbered_dir(path)
      assert not os.path.isdir(extended_path)
  
  
  def test_get_extended_length_path_str():
      assert get_extended_length_path_str(r"c:\foo") == r"\\?\c:\foo"
      assert get_extended_length_path_str(r"\\share\foo") == r"\\?\UNC\share\foo"
      assert get_extended_length_path_str(r"\\?\UNC\share\foo") == r"\\?\UNC\share\foo"
      assert get_extended_length_path_str(r"\\?\c:\foo") == r"\\?\c:\foo"
  
  
  def test_suppress_error_removing_lock(tmp_path):
      """ensure_deletable should be resilient if lock file cannot be removed (#5456, #7491)"""
      path = tmp_path / "dir"
      path.mkdir()
      lock = get_lock_path(path)
      lock.touch()
      mtime = lock.stat().st_mtime
  
      with unittest.mock.patch.object(Path, "unlink", side_effect=OSError) as m:
          assert not ensure_deletable(
              path, consider_lock_dead_if_created_before=mtime + 30
          )
          assert m.call_count == 1
      assert lock.is_file()
  
      with unittest.mock.patch.object(Path, "is_file", side_effect=OSError) as m:
          assert not ensure_deletable(
              path, consider_lock_dead_if_created_before=mtime + 30
          )
          assert m.call_count == 1
      assert lock.is_file()
  
      # check now that we can remove the lock file in normal circumstances
      assert ensure_deletable(path, consider_lock_dead_if_created_before=mtime + 30)
      assert not lock.is_file()
  