summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hahler <git@thequod.de>2020-01-12 06:44:34 +0100
committerRan Benita <ran@unusedvar.com>2020-06-23 19:39:44 +0300
commit59fd0d5f00767b13f8273e5f3ca48952a2d99916 (patch)
tree45071d312cf49501c6e9fdd001e65d96d7a2b960
parentd6aad8482f1657b68f8cb99f4c55ffa98a81b655 (diff)
downloadpy-59fd0d5f00767b13f8273e5f3ca48952a2d99916.tar.gz
Add type stubs
Add complete type stubs to the public interface of some of `py`s modules. The modules are those used by `pytest`. The types are marked as partial, so uncovered modules should be unaffected. Co-authored-by: Ran Benita <ran@unusedvar.com>.
-rw-r--r--.flake84
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG16
-rw-r--r--MANIFEST.in1
-rw-r--r--py/__init__.pyi20
-rw-r--r--py/_io/capture.py6
-rw-r--r--py/error.pyi129
-rw-r--r--py/iniconfig.pyi31
-rw-r--r--py/io.pyi130
-rw-r--r--py/path.pyi197
-rw-r--r--py/py.typed0
-rw-r--r--py/xml.pyi25
-rw-r--r--setup.py4
13 files changed, 561 insertions, 3 deletions
diff --git a/.flake8 b/.flake8
new file mode 100644
index 00000000..f9c71a7f
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,4 @@
+[flake8]
+max-line-length = 120
+per-file-ignores =
+ **/*.pyi:E252,E301,E302,E305,E501,E701,E704,F401,F811,F821
diff --git a/.gitignore b/.gitignore
index 375476fd..fa936f15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.cache/
.tox/
__pycache__/
+.mypy_cache/
*.pyc
*.pyo
diff --git a/CHANGELOG b/CHANGELOG
index 3fbc0724..dc807a7d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,19 @@
+1.9.0 (TBD)
+===========
+
+- Add type annotation stubs for the following modules:
+ * ``py.error``
+ * ``py.iniconfig``
+ * ``py.path`` (not including SVN paths)
+ * ``py.io``
+ * ``py.xml``
+ There are no plans to type other modules at this time.
+
+ The type annotations are provided in external .pyi files, not inline in the
+ code, and may therefore contain small errors or omissions. If you use ``py``
+ in conjunction with a type checker, and encounter any type errors you believe
+ should be accepted, please report it in an issue.
+
1.8.2 (2020-06-15)
==================
diff --git a/MANIFEST.in b/MANIFEST.in
index 239ad228..afa7ad66 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -5,6 +5,7 @@ include setup.py
include LICENSE
include conftest.py
include tox.ini
+recursive-include py *.pyi
graft doc
graft testing
global-exclude *.pyc
diff --git a/py/__init__.pyi b/py/__init__.pyi
new file mode 100644
index 00000000..96859e31
--- /dev/null
+++ b/py/__init__.pyi
@@ -0,0 +1,20 @@
+from typing import Any
+
+# py allows to use e.g. py.path.local even without importing py.path.
+# So import implicitly.
+from . import error
+from . import iniconfig
+from . import path
+from . import io
+from . import xml
+
+__version__: str
+
+# Untyped modules below here.
+std: Any
+test: Any
+process: Any
+apipkg: Any
+code: Any
+builtin: Any
+log: Any
diff --git a/py/_io/capture.py b/py/_io/capture.py
index bc157ed9..cacf2fa7 100644
--- a/py/_io/capture.py
+++ b/py/_io/capture.py
@@ -13,7 +13,7 @@ if sys.version_info < (3,0):
def write(self, data):
if not isinstance(data, unicode):
data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace')
- StringIO.write(self, data)
+ return StringIO.write(self, data)
else:
TextIO = StringIO
@@ -24,7 +24,7 @@ except ImportError:
def write(self, data):
if isinstance(data, unicode):
raise TypeError("not a byte value: %r" %(data,))
- StringIO.write(self, data)
+ return StringIO.write(self, data)
patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
@@ -266,7 +266,7 @@ class StdCaptureFD(Capture):
err = self._readsnapshot(self.err.tmpfile)
else:
err = ""
- return [out, err]
+ return out, err
def _readsnapshot(self, f):
f.seek(0)
diff --git a/py/error.pyi b/py/error.pyi
new file mode 100644
index 00000000..034eba60
--- /dev/null
+++ b/py/error.pyi
@@ -0,0 +1,129 @@
+from typing import Any, Callable, TypeVar
+
+_T = TypeVar('_T')
+
+def checked_call(func: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ...
+class Error(EnvironmentError): ...
+class EPERM(Error): ...
+class ENOENT(Error): ...
+class ESRCH(Error): ...
+class EINTR(Error): ...
+class EIO(Error): ...
+class ENXIO(Error): ...
+class E2BIG(Error): ...
+class ENOEXEC(Error): ...
+class EBADF(Error): ...
+class ECHILD(Error): ...
+class EAGAIN(Error): ...
+class ENOMEM(Error): ...
+class EACCES(Error): ...
+class EFAULT(Error): ...
+class ENOTBLK(Error): ...
+class EBUSY(Error): ...
+class EEXIST(Error): ...
+class EXDEV(Error): ...
+class ENODEV(Error): ...
+class ENOTDIR(Error): ...
+class EISDIR(Error): ...
+class EINVAL(Error): ...
+class ENFILE(Error): ...
+class EMFILE(Error): ...
+class ENOTTY(Error): ...
+class ETXTBSY(Error): ...
+class EFBIG(Error): ...
+class ENOSPC(Error): ...
+class ESPIPE(Error): ...
+class EROFS(Error): ...
+class EMLINK(Error): ...
+class EPIPE(Error): ...
+class EDOM(Error): ...
+class ERANGE(Error): ...
+class EDEADLCK(Error): ...
+class ENAMETOOLONG(Error): ...
+class ENOLCK(Error): ...
+class ENOSYS(Error): ...
+class ENOTEMPTY(Error): ...
+class ELOOP(Error): ...
+class EWOULDBLOCK(Error): ...
+class ENOMSG(Error): ...
+class EIDRM(Error): ...
+class ECHRNG(Error): ...
+class EL2NSYNC(Error): ...
+class EL3HLT(Error): ...
+class EL3RST(Error): ...
+class ELNRNG(Error): ...
+class EUNATCH(Error): ...
+class ENOCSI(Error): ...
+class EL2HLT(Error): ...
+class EBADE(Error): ...
+class EBADR(Error): ...
+class EXFULL(Error): ...
+class ENOANO(Error): ...
+class EBADRQC(Error): ...
+class EBADSLT(Error): ...
+class EDEADLOCK(Error): ...
+class EBFONT(Error): ...
+class ENOSTR(Error): ...
+class ENODATA(Error): ...
+class ETIME(Error): ...
+class ENOSR(Error): ...
+class ENONET(Error): ...
+class ENOPKG(Error): ...
+class EREMOTE(Error): ...
+class ENOLINK(Error): ...
+class EADV(Error): ...
+class ESRMNT(Error): ...
+class ECOMM(Error): ...
+class EPROTO(Error): ...
+class EMULTIHOP(Error): ...
+class EDOTDOT(Error): ...
+class EBADMSG(Error): ...
+class EOVERFLOW(Error): ...
+class ENOTUNIQ(Error): ...
+class EBADFD(Error): ...
+class EREMCHG(Error): ...
+class ELIBACC(Error): ...
+class ELIBBAD(Error): ...
+class ELIBSCN(Error): ...
+class ELIBMAX(Error): ...
+class ELIBEXEC(Error): ...
+class EILSEQ(Error): ...
+class ERESTART(Error): ...
+class ESTRPIPE(Error): ...
+class EUSERS(Error): ...
+class ENOTSOCK(Error): ...
+class EDESTADDRREQ(Error): ...
+class EMSGSIZE(Error): ...
+class EPROTOTYPE(Error): ...
+class ENOPROTOOPT(Error): ...
+class EPROTONOSUPPORT(Error): ...
+class ESOCKTNOSUPPORT(Error): ...
+class ENOTSUP(Error): ...
+class EOPNOTSUPP(Error): ...
+class EPFNOSUPPORT(Error): ...
+class EAFNOSUPPORT(Error): ...
+class EADDRINUSE(Error): ...
+class EADDRNOTAVAIL(Error): ...
+class ENETDOWN(Error): ...
+class ENETUNREACH(Error): ...
+class ENETRESET(Error): ...
+class ECONNABORTED(Error): ...
+class ECONNRESET(Error): ...
+class ENOBUFS(Error): ...
+class EISCONN(Error): ...
+class ENOTCONN(Error): ...
+class ESHUTDOWN(Error): ...
+class ETOOMANYREFS(Error): ...
+class ETIMEDOUT(Error): ...
+class ECONNREFUSED(Error): ...
+class EHOSTDOWN(Error): ...
+class EHOSTUNREACH(Error): ...
+class EALREADY(Error): ...
+class EINPROGRESS(Error): ...
+class ESTALE(Error): ...
+class EUCLEAN(Error): ...
+class ENOTNAM(Error): ...
+class ENAVAIL(Error): ...
+class EISNAM(Error): ...
+class EREMOTEIO(Error): ...
+class EDQUOT(Error): ...
diff --git a/py/iniconfig.pyi b/py/iniconfig.pyi
new file mode 100644
index 00000000..79b5e6ad
--- /dev/null
+++ b/py/iniconfig.pyi
@@ -0,0 +1,31 @@
+from typing import Callable, Iterator, Mapping, Optional, Tuple, TypeVar, Union
+from typing_extensions import Final
+
+_D = TypeVar('_D')
+_T = TypeVar('_T')
+
+class ParseError(Exception):
+ path: Final[str]
+ lineno: Final[int]
+ msg: Final[str]
+ def __init__(self, path: str, lineno: int, msg: str) -> None: ...
+
+class _SectionWrapper:
+ config: Final[IniConfig]
+ name: Final[str]
+ def __init__(self, config: IniConfig, name: str) -> None: ...
+ def __getitem__(self, key: str) -> Optional[str]: ...
+ def __iter__(self) -> Iterator[str]: ...
+ def get(self, key: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ...
+ def items(self) -> Iterator[Tuple[str, Optional[str]]]: ...
+ def lineof(self, name: str) -> Optional[int]: ...
+
+class IniConfig:
+ path: Final[str]
+ sections: Final[Mapping[str, Mapping[str, Optional[str]]]]
+ def __init__(self, path: str, data: Optional[str] = None): ...
+ def __contains__(self, arg: str) -> bool: ...
+ def __getitem__(self, name: str) -> _SectionWrapper: ...
+ def __iter__(self) -> Iterator[_SectionWrapper]: ...
+ def get(self, section: str, name: str, default: _D = ..., convert: Callable[[Optional[str]], _T] = ...) -> Union[_T, _D]: ...
+ def lineof(self, section: str, name: Optional[str] = ...) -> Optional[int]: ...
diff --git a/py/io.pyi b/py/io.pyi
new file mode 100644
index 00000000..d377e240
--- /dev/null
+++ b/py/io.pyi
@@ -0,0 +1,130 @@
+from io import StringIO as TextIO
+from io import BytesIO as BytesIO
+from typing import Any, AnyStr, Callable, Generic, IO, List, Optional, Text, Tuple, TypeVar, Union, overload
+from typing_extensions import Final
+import sys
+
+_T = TypeVar("_T")
+
+class FDCapture(Generic[AnyStr]):
+ def __init__(self, targetfd: int, tmpfile: Optional[IO[AnyStr]] = ..., now: bool = ..., patchsys: bool = ...) -> None: ...
+ def start(self) -> None: ...
+ def done(self) -> IO[AnyStr]: ...
+ def writeorg(self, data: AnyStr) -> None: ...
+
+class StdCaptureFD:
+ def __init__(
+ self,
+ out: Union[bool, IO[str]] = ...,
+ err: Union[bool, IO[str]] = ...,
+ mixed: bool = ...,
+ in_: bool = ...,
+ patchsys: bool = ...,
+ now: bool = ...,
+ ) -> None: ...
+ @classmethod
+ def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ...
+ def reset(self) -> Tuple[str, str]: ...
+ def suspend(self) -> Tuple[str, str]: ...
+ def startall(self) -> None: ...
+ def resume(self) -> None: ...
+ def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ...
+ def readouterr(self) -> Tuple[str, str]: ...
+
+class StdCapture:
+ def __init__(
+ self,
+ out: Union[bool, IO[str]] = ...,
+ err: Union[bool, IO[str]] = ...,
+ in_: bool = ...,
+ mixed: bool = ...,
+ now: bool = ...,
+ ) -> None: ...
+ @classmethod
+ def call(cls, func: Callable[..., _T], *args: Any, **kwargs: Any) -> Tuple[_T, str, str]: ...
+ def reset(self) -> Tuple[str, str]: ...
+ def suspend(self) -> Tuple[str, str]: ...
+ def startall(self) -> None: ...
+ def resume(self) -> None: ...
+ def done(self, save: bool = ...) -> Tuple[IO[str], IO[str]]: ...
+ def readouterr(self) -> Tuple[IO[str], IO[str]]: ...
+
+# XXX: The type here is not exactly right. If f is IO[bytes] and
+# encoding is not None, returns some weird hybrid, not exactly IO[bytes].
+def dupfile(
+ f: IO[AnyStr],
+ mode: Optional[str] = ...,
+ buffering: int = ...,
+ raising: bool = ...,
+ encoding: Optional[str] = ...,
+) -> IO[AnyStr]: ...
+def get_terminal_width() -> int: ...
+def ansi_print(
+ text: Union[str, Text],
+ esc: Union[Union[str, Text], Tuple[Union[str, Text], ...]],
+ file: Optional[IO[Any]] = ...,
+ newline: bool = ...,
+ flush: bool = ...,
+) -> None: ...
+def saferepr(obj, maxsize: int = ...) -> str: ...
+
+class TerminalWriter:
+ stringio: TextIO
+ encoding: Final[str]
+ hasmarkup: bool
+ def __init__(self, file: Optional[IO[str]] = ..., stringio: bool = ..., encoding: Optional[str] = ...) -> None: ...
+ @property
+ def fullwidth(self) -> int: ...
+ @fullwidth.setter
+ def fullwidth(self, value: int) -> None: ...
+ @property
+ def chars_on_current_line(self) -> int: ...
+ @property
+ def width_of_current_line(self) -> int: ...
+ def markup(
+ self,
+ text: str,
+ *,
+ black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ...,
+ cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ...,
+ Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ...,
+ blink: int = ..., invert: int = ...,
+ ) -> str: ...
+ def sep(
+ self,
+ sepchar: str,
+ title: Optional[str] = ...,
+ fullwidth: Optional[int] = ...,
+ *,
+ black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ...,
+ cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ...,
+ Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ...,
+ blink: int = ..., invert: int = ...,
+ ) -> None: ...
+ def write(
+ self,
+ msg: str,
+ *,
+ black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ...,
+ cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ...,
+ Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ...,
+ blink: int = ..., invert: int = ...,
+ ) -> None: ...
+ def line(
+ self,
+ s: str = ...,
+ *,
+ black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ...,
+ cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ...,
+ Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ...,
+ blink: int = ..., invert: int = ...,
+ ) -> None: ...
+ def reline(
+ self,
+ line: str,
+ *,
+ black: int = ..., red: int = ..., green: int = ..., yellow: int = ..., blue: int = ..., purple: int = ...,
+ cyan: int = ..., white: int = ..., Black: int = ..., Red: int = ..., Green: int = ..., Yellow: int = ...,
+ Blue: int = ..., Purple: int = ..., Cyan: int = ..., White: int = ..., bold: int = ..., light: int = ...,
+ blink: int = ..., invert: int = ...,
+ ) -> None: ...
diff --git a/py/path.pyi b/py/path.pyi
new file mode 100644
index 00000000..1ddab960
--- /dev/null
+++ b/py/path.pyi
@@ -0,0 +1,197 @@
+from typing import Any, AnyStr, Callable, ContextManager, Generic, IO, Iterable, Iterator, List, Optional, Text, Type, Union
+from typing_extensions import Final, Literal
+import os
+import sys
+
+class _FNMatcher(Generic[AnyStr]):
+ pattern: AnyStr = ...
+ def __init__(self, pattern: AnyStr) -> None: ...
+ def __call__(self, path: local) -> bool: ...
+
+class _Stat:
+ path: Final[local] = ...
+ mode: Final[int]
+ ino: Final[int]
+ dev: Final[int]
+ nlink: Final[int]
+ uid: Final[int]
+ gid: Final[int]
+ size: Final[int]
+ atime: Final[float]
+ mtime: Final[float]
+ ctime: Final[float]
+ atime_ns: Final[int]
+ mtime_ns: Final[int]
+ ctime_ns: Final[int]
+ if sys.version_info >= (3, 8) and sys.platform == "win32":
+ reparse_tag: Final[int]
+ blocks: Final[int]
+ blksize: Final[int]
+ rdev: Final[int]
+ flags: Final[int]
+ gen: Final[int]
+ birthtime: Final[int]
+ rsize: Final[int]
+ creator: Final[int]
+ type: Final[int]
+ if sys.platform != 'win32':
+ @property
+ def owner(self) -> str: ...
+ @property
+ def group(self) -> str: ...
+ def isdir(self) -> bool: ...
+ def isfile(self) -> bool: ...
+ def islink(self) -> bool: ...
+
+
+if sys.version_info >= (3, 6):
+ _PathLike = os.PathLike
+else:
+ class _PathLike(Generic[AnyStr]):
+ def __fspath__(self) -> AnyStr: ...
+_PathType = Union[bytes, Text, _PathLike[str], _PathLike[bytes], local]
+
+class local(_PathLike[str]):
+ class ImportMismatchError(ImportError): ...
+
+ sep: Final[str]
+ strpath: Final[str]
+
+ def __init__(self, path: _PathType = ..., expanduser: bool = ...) -> None: ...
+ def __hash__(self) -> int: ...
+ def __eq__(self, other: object) -> bool: ...
+ def __ne__(self, other: object) -> bool: ...
+ def __lt__(self, other: object) -> bool: ...
+ def __gt__(self, other: object) -> bool: ...
+ def __add__(self, other: object) -> local: ...
+ def __cmp__(self, other: object) -> int: ...
+ def __div__(self, other: _PathType) -> local: ...
+ def __truediv__(self, other: _PathType) -> local: ...
+ def __fspath__(self) -> str: ...
+
+ @classmethod
+ def get_temproot(cls) -> local: ...
+ @classmethod
+ def make_numbered_dir(
+ cls,
+ prefix: str = ...,
+ rootdir: Optional[local] = ...,
+ keep: Optional[int] = ...,
+ lock_timeout: int = ...,
+ ) -> local: ...
+ @classmethod
+ def mkdtemp(cls, rootdir: Optional[local] = ...) -> local: ...
+ @classmethod
+ def sysfind(
+ cls,
+ name: _PathType,
+ checker: Optional[Callable[[local], bool]] = ...,
+ paths: Optional[Iterable[_PathType]] = ...,
+ ) -> Optional[local]: ...
+
+ @property
+ def basename(self) -> str: ...
+ @property
+ def dirname(self) -> str: ...
+ @property
+ def purebasename(self) -> str: ...
+ @property
+ def ext(self) -> str: ...
+
+ def as_cwd(self) -> ContextManager[Optional[local]]: ...
+ def atime(self) -> float: ...
+ def bestrelpath(self, dest: local) -> str: ...
+ def chdir(self) -> local: ...
+ def check(
+ self,
+ *,
+ basename: int = ..., notbasename: int = ...,
+ basestarts: int = ..., notbasestarts: int = ...,
+ dir: int = ..., notdir: int = ...,
+ dotfile: int = ..., notdotfile: int = ...,
+ endswith: int = ..., notendswith: int = ...,
+ exists: int = ..., notexists: int = ...,
+ ext: int = ..., notext: int = ...,
+ file: int = ..., notfile: int = ...,
+ fnmatch: int = ..., notfnmatch: int = ...,
+ link: int = ..., notlink: int = ...,
+ relto: int = ..., notrelto: int = ...,
+ ) -> bool: ...
+ def chmod(self, mode: int, rec: Union[int, str, Text, Callable[[local], bool]] = ...) -> None: ...
+ if sys.platform != 'win32':
+ def chown(self, user: Union[int, str], group: Union[int, str], rec: int = ...) -> None: ...
+ def common(self, other: local) -> Optional[local]: ...
+ def computehash(self, hashtype: str = ..., chunksize: int = ...) -> str: ...
+ def copy(self, target: local, mode: bool = ..., stat: bool = ...) -> None: ...
+ def dirpath(self, *args: _PathType, abs: int = ...) -> local: ...
+ def dump(self, obj: Any, bin: Optional[int] = ...) -> None: ...
+ def ensure(self, *args: _PathType, dir: int = ...) -> local: ...
+ def ensure_dir(self, *args: _PathType) -> local: ...
+ def exists(self) -> bool: ...
+ def fnmatch(self, pattern: str): _FNMatcher
+ def isdir(self) -> bool: ...
+ def isfile(self) -> bool: ...
+ def islink(self) -> bool: ...
+ def join(self, *args: _PathType, abs: int = ...) -> local: ...
+ def listdir(
+ self,
+ fil: Optional[Union[str, Text, Callable[[local], bool]]] = ...,
+ sort: Optional[bool] = ...,
+ ) -> List[local]: ...
+ def load(self) -> Any: ...
+ def lstat(self) -> _Stat: ...
+ def mkdir(self, *args: _PathType) -> local: ...
+ if sys.platform != 'win32':
+ def mklinkto(self, oldname: Union[str, local]) -> None: ...
+ def mksymlinkto(self, value: local, absolute: int = ...) -> None: ...
+ def move(self, target: local) -> None: ...
+ def mtime(self) -> float: ...
+ def new(
+ self,
+ *,
+ drive: str = ...,
+ dirname: str = ...,
+ basename: str = ...,
+ purebasename: str = ...,
+ ext: str = ...,
+ ) -> local: ...
+ def open(self, mode: str = ..., ensure: bool = ..., encoding: Optional[str] = ...) -> IO[Any]: ...
+ def parts(self, reverse: bool = ...) -> List[local]: ...
+ def pyimport(
+ self,
+ modname: Optional[str] = ...,
+ ensuresyspath: Union[bool, Literal["append", "importlib"]] = ...,
+ ) -> Any: ...
+ def pypkgpath(self) -> Optional[local]: ...
+ def read(self, mode: str = ...) -> Union[Text, bytes]: ...
+ def read_binary(self) -> bytes: ...
+ def read_text(self, encoding: str) -> Text: ...
+ def readlines(self, cr: int = ...) -> List[str]: ...
+ if sys.platform != 'win32':
+ def readlink(self) -> str: ...
+ def realpath(self) -> local: ...
+ def relto(self, relpath: Union[str, local]) -> str: ...
+ def remove(self, rec: int = ..., ignore_errors: bool = ...) -> None: ...
+ def rename(self, target: _PathType) -> None: ...
+ def samefile(self, other: _PathType) -> bool: ...
+ def setmtime(self, mtime: Optional[float] = ...) -> None: ...
+ def size(self) -> int: ...
+ def stat(self, raising: bool = ...) -> _Stat: ...
+ def sysexec(self, *argv: Any, **popen_opts: Any) -> Text: ...
+ def visit(
+ self,
+ fil: Optional[Union[str, Text, Callable[[local], bool]]] = ...,
+ rec: Optional[Union[Literal[1, True], str, Text, Callable[[local], bool]]] = ...,
+ ignore: Type[Exception] = ...,
+ bf: bool = ...,
+ sort: bool = ...,
+ ) -> Iterator[local]: ...
+ def write(self, data: Any, mode: str = ..., ensure: bool = ...) -> None: ...
+ def write_binary(self, data: bytes, ensure: bool = ...) -> None: ...
+ def write_text(self, data: Union[str, Text], encoding: str, ensure: bool = ...) -> None: ...
+
+
+# Untyped types below here.
+svnwc: Any
+svnurl: Any
+SvnAuth: Any
diff --git a/py/py.typed b/py/py.typed
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/py/py.typed
diff --git a/py/xml.pyi b/py/xml.pyi
new file mode 100644
index 00000000..9c44480a
--- /dev/null
+++ b/py/xml.pyi
@@ -0,0 +1,25 @@
+from typing import ClassVar, Generic, Iterable, Text, Type, Union
+from typing_extensions import Final
+
+class raw:
+ uniobj: Final[Text]
+ def __init__(self, uniobj: Text) -> None: ...
+
+class _NamespaceMetaclass(type):
+ def __getattr__(self, name: str) -> Type[Tag]: ...
+
+class Namespace(metaclass=_NamespaceMetaclass): ...
+
+class Tag(list):
+ class Attr:
+ def __getattr__(self, attr: str) -> Text: ...
+ attr: Final[Attr]
+ def __init__(self, *args: Union[Text, raw, Tag, Iterable[Tag]], **kwargs: Union[Text, raw]) -> None: ...
+ def unicode(self, indent: int = ...) -> Text: ...
+
+class html(Namespace):
+ class Style:
+ def __init__(self, **kw: Union[str, Text]) -> None: ...
+ style: ClassVar[Style]
+
+def escape(ustring: Union[str, Text]) -> Text: ...
diff --git a/setup.py b/setup.py
index 45395abd..d097daa5 100644
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,11 @@ def main():
'Programming Language :: Python :: Implementation :: PyPy',
],
packages=find_packages(exclude=['tasks', 'testing']),
+ include_package_data=True,
zip_safe=False,
+ package_data={
+ "": ["py.typed"],
+ },
)
if __name__ == '__main__':