Skip to main content
Use an __init__ method and get rid of from_path.
Source Link
Booboo
  • 3.5k
  • 4
  • 14

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.password = password

        return instance

And, of course, as suggested by the OP, if we are no longer using the @dataclass decorator we can incorporate the logic of from_path class method into an __init__ constructor and get rid of from_path altogether:

class RarFile:
    def __init__(self, archive_path: pathlib.Path, password: str | None = None) -> typing.Self:
        """Create a RarFile object by reading information from a RAR archive given its path."""
        infos = self.list_rar(archive_path, password)  # Now an instance method
        ...
        self.version = version
        self.path = archive_path
        self.files = files
        self.password = password

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.password = password

        return instance

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.password = password

        return instance

And, of course, as suggested by the OP, if we are no longer using the @dataclass decorator we can incorporate the logic of from_path class method into an __init__ constructor and get rid of from_path altogether:

class RarFile:
    def __init__(self, archive_path: pathlib.Path, password: str | None = None) -> typing.Self:
        """Create a RarFile object by reading information from a RAR archive given its path."""
        infos = self.list_rar(archive_path, password)  # Now an instance method
        ...
        self.version = version
        self.path = archive_path
        self.files = files
        self.password = password
added 4 characters in body
Source Link
Booboo
  • 3.5k
  • 4
  • 14

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.passpassword = versionpassword

        return instance

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.pass = version

        return instance

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.password = password

        return instance
Source Link
Booboo
  • 3.5k
  • 4
  • 14

In addition to what has already be said, here are a couple suggestions for you to consider:

Encapsulation

Your module has functions get_crc32_slow, list_rar used by your RarFile class and I am wondering why they are not be instance methods of RarFile. Even if you think that these functions might have applicability beyond their use by RarFile, since they are RAR file-related functions, wouldn't making then class methods at the very least be appropriate?

Why @dataclass?

The @dataclass decorator is adding many methods to your class that you do not seem to be using. At the same time it seems to me that a client of this class would most likely be always constructing an instance via the from_path class method and you might even want to make that the exclusive way of constructing instances. But with the class defined as is, there is no way of preventing someone from constructing via the __init__ method that @dataclass provides. Assuming you would prefer to discourage a client from directly using __init__, then this would be one way of doing it:

# No @dataclass decorator:
class RarFile:
    def __init__(self):
        raise RuntimeError('Construct this class using class method from_path')


    @classmethod
    def from_path(
        cls, archive_path: pathlib.Path, password: str | None = None
    ) -> typing.Self:
        ...

        #return cls(version, archive_path, files, password)

        instance = cls.__new__(cls)

        instance.version = version
        instance.path = archive_path
        instance.files = files
        instance.pass = version

        return instance