Skip to content

Commit 006bdbe

Browse files
committed
Initial v0.0.1
1 parent a95f53d commit 006bdbe

8 files changed

Lines changed: 185 additions & 1 deletion

File tree

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "src/mvarcs"]
2+
path = src/mvarcs
3+
url = https://github.com/markcerts/mvarcs
4+
branch = initial-certs

README.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,51 @@
1-
# mvarcs-python
1+
# mvarcs: Python Mark Verifying Authority Root Certificates
2+
3+
mvarcs provides a collection of Root Certificates for validating
4+
the trustworthiness of Mark Certificates such as Verified Mark
5+
Certificates (VMC) and Common Mark Certificates (CMC) used in BIMI
6+
(Brand Indicators for Message Identification).
7+
8+
Current status: **Alpha**
9+
10+
## Installation
11+
12+
``mvarcs`` is available on PyPI. Simply install it with ``pip``:
13+
14+
``` sh
15+
python -m pip install mvarcs
16+
```
17+
18+
## Usage
19+
20+
To reference the installed certificate authority (CA) bundle, you can use the
21+
built-in function
22+
23+
``` py
24+
import mvarcs
25+
mvarcs.where()
26+
# '/usr/local/lib/python3.13/site-packages/mvarcs/mvarcs/cacerts.pem'
27+
```
28+
29+
Additionally, you can get the contents directly
30+
31+
``` py
32+
import mvarcs
33+
mvarcs.contents()
34+
# Issuer: ...
35+
# ...
36+
# -----END CERTIFICATE-----
37+
```
38+
39+
Or from the command line
40+
``` sh
41+
python -m mvarcs
42+
# /usr/local/lib/python3.13/site-packages/mvarcs/mvarcs/cacert.pem
43+
44+
python -m mvarcs -c
45+
# Issuer: ...
46+
# ...
47+
# -----END CERTIFICATE-----
48+
```
49+
50+
## Addition/Removal of Certificates
51+
See https://github.com/markcerts/mvarcs

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build-system]
2+
requires = ['setuptools>=42']
3+
build-backend = 'setuptools.build_meta'

setup.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import setuptools
2+
3+
with open("README.md", "r", encoding="utf-8") as fh:
4+
long_description = fh.read()
5+
6+
setuptools.setup(
7+
name="mvarcs",
8+
version="0.0.1",
9+
author="OllieJC",
10+
author_email="mvarcs-pypi@olliejc.uk",
11+
description="Python package for providing the MVARCS",
12+
long_description=long_description,
13+
long_description_content_type="text/markdown",
14+
url="https://github.com/markcerts/mvarcs-python",
15+
project_urls={
16+
"Bug Tracker": "https://github.com/markcerts/mvarcs-python/issues",
17+
"MVARCS": "https://github.com/markcerts/mvarcs",
18+
},
19+
license="The Unlicense",
20+
classifiers=[
21+
"Development Status :: 3 - Alpha",
22+
"Intended Audience :: Developers",
23+
"License :: OSI Approved :: The Unlicense (Unlicense)",
24+
"Programming Language :: Python :: 3",
25+
"Natural Language :: English",
26+
"Operating System :: OS Independent",
27+
],
28+
package_dir={"mvarcs": "src"},
29+
package_data={"mvarcs": ["mvarcs/*.pem"]},
30+
packages=["mvarcs"],
31+
python_requires=">=3.6",
32+
)

src/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .core import contents, where
2+
3+
__all__ = ["contents", "where"]
4+
__version__ = "2024.12.24"

src/__main__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import argparse
2+
3+
from mvarcs import contents, where
4+
5+
parser = argparse.ArgumentParser()
6+
parser.add_argument("-c", "--contents", action="store_true")
7+
args = parser.parse_args()
8+
9+
if args.contents:
10+
print(contents())
11+
else:
12+
print(where())

src/core.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
This module returns the installation location of cacert.pem or its contents.
3+
4+
Functionality derived from https://github.com/certifi/python-certifi/blob/master/certifi/core.py
5+
"""
6+
7+
import sys
8+
import atexit
9+
10+
11+
def exit_MVARCS_CTX() -> None:
12+
_MVARCS_CTX.__exit__(None, None, None) # type: ignore[union-attr]
13+
14+
15+
if sys.version_info >= (3, 11):
16+
17+
from importlib.resources import as_file, files
18+
19+
_MVARCS_CTX = None
20+
_MVARCS_PATH = None
21+
22+
def where() -> str:
23+
# This is slightly terrible, but we want to delay extracting the file
24+
# in cases where we're inside of a zipimport situation until someone
25+
# actually calls where(), but we don't want to re-extract the file
26+
# on every call of where(), so we'll do it once then store it in a
27+
# global variable.
28+
global _MVARCS_CTX
29+
global _MVARCS_PATH
30+
if _MVARCS_PATH is None:
31+
# This is slightly janky, the importlib.resources API wants you to
32+
# manage the cleanup of this file, so it doesn't actually return a
33+
# path, it returns a context manager that will give you the path
34+
# when you enter it and will do any cleanup when you leave it. In
35+
# the common case of not needing a temporary file, it will just
36+
# return the file system location and the __exit__() is a no-op.
37+
#
38+
# We also have to hold onto the actual context manager, because
39+
# it will do the cleanup whenever it gets garbage collected, so
40+
# we will also store that at the global level as well.
41+
_MVARCS_CTX = as_file(files("mvarcs").joinpath("mvarcs/cacert.pem"))
42+
_MVARCS_PATH = str(_MVARCS_CTX.__enter__())
43+
atexit.register(exit_MVARCS_CTX)
44+
45+
return _MVARCS_PATH
46+
47+
def contents() -> str:
48+
return files("mvarcs").joinpath("mvarcs/cacert.pem").read_text(encoding="ascii")
49+
50+
else:
51+
import os
52+
import types
53+
from typing import Union
54+
55+
Package = Union[types.ModuleType, str]
56+
Resource = Union[str, "os.PathLike"]
57+
58+
# This fallback will work for Python versions prior to 3.7 that lack the
59+
# importlib.resources module but relies on the existing `where` function
60+
# so won't address issues with environments like PyOxidizer that don't set
61+
# __file__ on modules.
62+
def read_text(
63+
package: Package,
64+
resource: Resource,
65+
encoding: str = "utf-8",
66+
errors: str = "strict",
67+
) -> str:
68+
with open(where(), encoding=encoding) as data:
69+
return data.read()
70+
71+
# If we don't have importlib.resources, then we will just do the old logic
72+
# of assuming we're on the filesystem and munge the path directly.
73+
def where() -> str:
74+
f = os.path.dirname(__file__)
75+
return os.path.join(f, os.path.join("mvarcs", "cacert.pem"))
76+
77+
def contents() -> str:
78+
return read_text("mvarcs", "mvarcs/cacert.pem", encoding="ascii")

src/mvarcs

Submodule mvarcs added at de06ade

0 commit comments

Comments
 (0)