Skip to content

Avoid calling __init__ for classmethod/staticmethod #450

@saluto

Description

@saluto

Suppose we want a CLI that is similar to git in the sense that we must first call init before interacting with the repo. For this, we aim for the following (simplified/partially implemented) class, which is intentionally similar to GitPythons Repo class (see here):

from pathlib import Path
import fire

class SomethingLikeGit:

  dirname = ".something_like_git"

  @classmethod
  def init(cls, path=None):
    path = Path(path or Path.cwd())
    path = path / cls.dirname
    print("Initializing at", path)
    path.mkdir()
    ...
    print("Done.")

  def __init__(self, path=None):
    path = Path(path or Path.cwd())
    for parent in (path, *path.parents):
      self.path = parent / self.dirname
      if self.path.exists():
        break
    else:
      raise FileNotFoundError(path)

  ...

if __name__ == "__main__":
  fire.Fire(SomethingLikeGit)

When we run the command python something_like_git.py init, it first tries to instantiate the class via __init__, which fails (FileNotFoundError) since it must first create the directory via init.
I think it makes generally more sense if Fire would call classmethods/staticmethods directly on the class without trying to instantiate it. This is usually also how class/static methods are used in a programmatic way (e.g. for git.Repo).

Note that the fix for #113 does not resolve this issue. This is because the path argument for __init__ is (intentionally) optional, so Fire thinks it can call __init__ first. If path wasn't optional, it would behave as wanted: init would be called without first calling __init__.

Anyway, thanks for your great work!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions