diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84496648..cadb14f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,18 @@ on: pull_request: {} jobs: + mypy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install dependencies + run: pip install mypy + - name: Run mypy + run: mypy --strict certifi + test: runs-on: ubuntu-latest strategy: diff --git a/certifi/__init__.py b/certifi/__init__.py index 8db1a0e5..41a722e4 100644 --- a/certifi/__init__.py +++ b/certifi/__init__.py @@ -1,3 +1,4 @@ from .core import contents, where +__all__ = ["contents", "where"] __version__ = "2021.10.08" diff --git a/certifi/core.py b/certifi/core.py index 5d2b8cd3..d768be79 100644 --- a/certifi/core.py +++ b/certifi/core.py @@ -7,6 +7,8 @@ This module returns the installation location of cacert.pem or its contents. """ import os +import types +from typing import Union try: from importlib.resources import path as get_path, read_text @@ -14,7 +16,7 @@ _CACERT_CTX = None _CACERT_PATH = None - def where(): + def where() -> str: # This is slightly terrible, but we want to delay extracting the file # in cases where we're inside of a zipimport situation until someone # actually calls where(), but we don't want to re-extract the file @@ -40,21 +42,29 @@ def where(): except ImportError: + Package = Union[types.ModuleType, str] + Resource = Union[str, "os.PathLike"] + # This fallback will work for Python versions prior to 3.7 that lack the # importlib.resources module but relies on the existing `where` function # so won't address issues with environments like PyOxidizer that don't set # __file__ on modules. - def read_text(_module, _path, encoding="ascii"): + def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict' + ) -> str: with open(where(), "r", encoding=encoding) as data: return data.read() # If we don't have importlib.resources, then we will just do the old logic # of assuming we're on the filesystem and munge the path directly. - def where(): + def where() -> str: f = os.path.dirname(__file__) return os.path.join(f, "cacert.pem") -def contents(): +def contents() -> str: return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/certifi/py.typed b/certifi/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/certifi/tests/test_certify.py b/certifi/tests/test_certify.py index 7fb8c77f..4b443f27 100755 --- a/certifi/tests/test_certify.py +++ b/certifi/tests/test_certify.py @@ -7,9 +7,14 @@ class TestCertifi(unittest.TestCase): - def test_cabundle_exists(self): + def test_cabundle_exists(self) -> None: assert os.path.exists(certifi.where()) - def test_read_contents(self): + def test_read_contents(self) -> None: content = certifi.contents() assert "-----BEGIN CERTIFICATE-----" in content + + def test_py_typed_exists(self) -> None: + assert os.path.exists( + os.path.join(os.path.dirname(certifi.__file__), 'py.typed') + ) diff --git a/setup.py b/setup.py index c3519635..48dc8912 100755 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ 'certifi', ], package_dir={'certifi': 'certifi'}, - package_data={'certifi': ['*.pem']}, + package_data={'certifi': ['*.pem', 'py.typed']}, # data_files=[('certifi', ['certifi/cacert.pem'])], include_package_data=True, zip_safe=False,