I've been trying to use a python tool called WindowsDowndate from github (for educational purposes, I've been given the task to demonstrate some Windows exploit) but running the code just does not work.
Windows_downdate.py imports numerous methods from another file called filesystem_utils.py, where the error takes place:
from windows_downdate.filesystem_utils import PathEx, is_file_contents_equal, is_path_exists, read_file, write_file
The PathEx class is defined in filesystem_utils as follows:
import filecmp
import os
from typing import Union, List, Any, TypeVar, Type, Self
from pathlib import WindowsPath, _from_parts
class PathEx(WindowsPath):
"""
Extended WindowsPath class that supports NT path
"""
TPathEx = TypeVar("TPathEx")
def __new__(cls: Type[TPathEx], path: str, *args: Any, **kwargs: Any) -> TPathEx:
"""
Create a new instance of PathEx, expanding environment variables in the provided path
:param path: The initial path
:param args: Additional positional arguments
:param kwargs: Additional keyword arguments
:return: A new instance of PathEx
"""
expanded_path = os.path.expandvars(path)
args = (expanded_path, ) + args
self = cls._from_parts(args)
return self
@property
def nt_path(self: Self) -> str:
"""
:return: The NT path as string
"""
return f"\\??\\{self.full_path}"
@property
def full_path(self: Self) -> str:
"""
:return: The full path as string
"""
return str(self)
I am a very amateur programmer so please forgive my ignorance, I don't quite know how to handle someone else's code.
Repository link: WindowsDowndate
I checked code in filesystem_utils.py and it has from pathlib import WindowsPath
without _from_parts
- maybe you use some old version.
But there can be different problem.
FULL error message/trackback should confirm it.
Source code for pathlib
in Python 3.11 shows that there was _from_parts
in class PurePath
but source code for Python 3.12 and Python 3.13 doesn't have it
If you use Python 3.11
then it should work. Eventually you need only to remove _from_parts
from line from pathlib import WindowsPath, _from_parts
(if you really have _from_parts
in this line) and keep only from pathlib import WindowsPath
and it should resolve this problem.
BTW: on repo you can even see (tested with python 3.11.9)
If you use Python 3.12/3.13
then you may copy this function from 3.11
and put in your PathEx
- but this also needs to copy other missing functions like _parse_args
, etc. and maybe it would be simpler to copy full module pathlib
for this
class PathEx(WindowsPath):
@classmethod
def _from_parts(cls, args):
# We need to call _parse_args on the instance, so as to get the
# right flavour.
self = object.__new__(cls)
drv, root, parts = self._parse_args(args)
self._drv = drv
self._root = root
self._parts = parts
return self
@classmethod
def _parse_args(cls, args):
# This is useful when you don't want to create an instance, just
# canonicalize some constructor arguments.
parts = []
for a in args:
if isinstance(a, PurePath):
parts += a._parts
else:
a = os.fspath(a)
if isinstance(a, str):
# Force-cast str subclasses to str (issue #21127)
parts.append(str(a))
else:
raise TypeError(
"argument should be a str object or an os.PathLike "
"object returning str, not %r"
% type(a))
return cls._flavour.parse_parts(parts)
Eventually you should check if other function in 3.12
/3.13
is doing the same and use it instead of _from_parts
Of course it also needs to remove _from_parts
from line from pathlib import WindowsPath