| 69 | return self.path |
| 70 | |
| 71 | def mktemp( |
| 72 | self, |
| 73 | name, # type: str |
| 74 | request=None, # type: Optional[Any] |
| 75 | ): |
| 76 | # type: (...) -> Tempdir |
| 77 | |
| 78 | long_name = None # type: Optional[str] |
| 79 | name = "{name}-{node}".format(name=name, node=request.node.name) if request else name |
| 80 | normalized_name = re.sub(r"\W", "_", name) |
| 81 | if len(normalized_name) > 30: |
| 82 | # The pytest implementation simply truncates at 30 which leads to collisions and this |
| 83 | # causes issues when tmpdir teardown is active - 1 test with the same 30 character |
| 84 | # prefix in its test name as another test can have its directories torn down out from |
| 85 | # underneath it! Here we ~ensure unique tmpdir names while preserving a filename length |
| 86 | # limit to play well with various file systems. |
| 87 | long_name = normalized_name |
| 88 | |
| 89 | # This is yields a ~1 in a million (5 hex chars at 4 bits a piece -> 2^20) chance of |
| 90 | # collision if the 1st 24 characters of the test name match. |
| 91 | prefix = normalized_name[:24] |
| 92 | fingerprint = hashlib.sha1(normalized_name.encode("utf-8")).hexdigest()[:5] |
| 93 | normalized_name = "{prefix}-{hash}".format(prefix=prefix, hash=fingerprint) |
| 94 | for index in range(_MAX_ATTEMPTS): |
| 95 | tempdir_name = "{name}{index}".format(name=normalized_name, index=index) |
| 96 | tempdir = os.path.join(self.path, tempdir_name) |
| 97 | try: |
| 98 | os.makedirs(tempdir) |
| 99 | symlink = None # type: Optional[str] |
| 100 | if long_name: |
| 101 | symlink = os.path.join(self.path, long_name) |
| 102 | safe_delete(symlink) |
| 103 | safe_symlink(tempdir_name, symlink) |
| 104 | return Tempdir(tempdir, symlink=symlink) |
| 105 | except OSError as e: |
| 106 | if e.errno == errno.EEXIST: |
| 107 | continue |
| 108 | raise OSError( |
| 109 | "Could not create numbered dir with prefix {prefix} in {root} after {max} tries".format( |
| 110 | prefix=normalized_name, root=self.path, max=_MAX_ATTEMPTS |
| 111 | ) |
| 112 | ) |
| 113 | |
| 114 | |
| 115 | def tmpdir_factory( |