pyhanko-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyhanko/__main__.py +9 -0
- pyhanko/cli/__init__.py +12 -0
- pyhanko/cli/_ctx.py +92 -0
- pyhanko/cli/_root.py +171 -0
- pyhanko/cli/_trust.py +159 -0
- pyhanko/cli/commands/__init__.py +0 -0
- pyhanko/cli/commands/crypt.py +219 -0
- pyhanko/cli/commands/fields.py +66 -0
- pyhanko/cli/commands/signing/__init__.py +328 -0
- pyhanko/cli/commands/signing/pkcs11_cli.py +185 -0
- pyhanko/cli/commands/signing/plugin.py +144 -0
- pyhanko/cli/commands/signing/simple.py +260 -0
- pyhanko/cli/commands/signing/utils.py +58 -0
- pyhanko/cli/commands/stamp.py +100 -0
- pyhanko/cli/commands/validation/__init__.py +2 -0
- pyhanko/cli/commands/validation/ltv.py +136 -0
- pyhanko/cli/commands/validation/validate.py +355 -0
- pyhanko/cli/config.py +306 -0
- pyhanko/cli/plugin_api.py +118 -0
- pyhanko/cli/py.typed +0 -0
- pyhanko/cli/runtime.py +80 -0
- pyhanko/cli/utils.py +68 -0
- pyhanko/cli/version.py +2 -0
- pyhanko_cli-0.1.0.dist-info/METADATA +68 -0
- pyhanko_cli-0.1.0.dist-info/RECORD +29 -0
- pyhanko_cli-0.1.0.dist-info/WHEEL +5 -0
- pyhanko_cli-0.1.0.dist-info/entry_points.txt +2 -0
- pyhanko_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- pyhanko_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import ClassVar, ContextManager, List, Optional
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
from pyhanko.cli._ctx import CLIContext
|
|
6
|
+
from pyhanko.sign import Signer
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
'SigningCommandPlugin',
|
|
10
|
+
'register_signing_plugin',
|
|
11
|
+
'CLIContext',
|
|
12
|
+
'SIGNING_PLUGIN_REGISTRY',
|
|
13
|
+
'SIGNING_PLUGIN_ENTRY_POINT_GROUP',
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SigningCommandPlugin(abc.ABC):
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
.. versionadded:: 0.18.0
|
|
21
|
+
|
|
22
|
+
Interface for integrating custom, user-supplied
|
|
23
|
+
signers into the pyHanko CLI as subcommands of ``addsig``.
|
|
24
|
+
|
|
25
|
+
Implementations are discovered through the ``pyhanko.cli_plugin.signing``
|
|
26
|
+
package entry point. Such entry points can be registered in
|
|
27
|
+
``pyproject.toml`` as follows:
|
|
28
|
+
|
|
29
|
+
.. code-block:: toml
|
|
30
|
+
|
|
31
|
+
[project.entry-points."pyhanko.cli_plugin.signing"]
|
|
32
|
+
your_plugin = "some_package.path.to.module:SomePluginClass"
|
|
33
|
+
|
|
34
|
+
Subclasses exposed as entry points are required to have a no-arguments
|
|
35
|
+
``__init__`` method.
|
|
36
|
+
|
|
37
|
+
.. warning::
|
|
38
|
+
This is an incubating feature. API adjustments are still possible.
|
|
39
|
+
|
|
40
|
+
.. warning::
|
|
41
|
+
Plugin support requires Python 3.8 or later.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
subcommand_name: ClassVar[str]
|
|
45
|
+
"""
|
|
46
|
+
The name of the subcommand for the plugin.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
help_summary: ClassVar[str]
|
|
50
|
+
"""
|
|
51
|
+
A short description of the plugin for use in the ``--help`` output.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
unavailable_message: ClassVar[Optional[str]] = None
|
|
55
|
+
"""
|
|
56
|
+
Message to display if the plugin is unavailable.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def click_options(self) -> List[click.Option]:
|
|
60
|
+
"""
|
|
61
|
+
The list of ``click`` options for your custom command.
|
|
62
|
+
"""
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
def click_extra_arguments(self) -> List[click.Argument]:
|
|
66
|
+
"""
|
|
67
|
+
The list of ``click`` arguments for your custom command.
|
|
68
|
+
"""
|
|
69
|
+
return []
|
|
70
|
+
|
|
71
|
+
def is_available(self) -> bool:
|
|
72
|
+
"""
|
|
73
|
+
A hook to determine whether your plugin is available
|
|
74
|
+
or not (e.g. based on the availability of certain dependencies).
|
|
75
|
+
This should not depend on the pyHanko configuration, but may query
|
|
76
|
+
system information in other ways as appropriate.
|
|
77
|
+
|
|
78
|
+
The default is to always report the plugin as available.
|
|
79
|
+
|
|
80
|
+
:return:
|
|
81
|
+
return ``True`` if the plugin is available, else ``False``
|
|
82
|
+
"""
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
def create_signer(
|
|
86
|
+
self, context: CLIContext, **kwargs
|
|
87
|
+
) -> ContextManager[Signer]:
|
|
88
|
+
"""
|
|
89
|
+
Instantiate a context manager that creates and potentially
|
|
90
|
+
also implements a deallocator for a :class:`.Signer` object.
|
|
91
|
+
|
|
92
|
+
:param context:
|
|
93
|
+
The active :class:`.CLIContext`.
|
|
94
|
+
:param kwargs:
|
|
95
|
+
All keyword arguments processed by ``click`` through the CLI,
|
|
96
|
+
resulting from :meth:`click_options` and
|
|
97
|
+
:meth:`click_extra_arguments`.
|
|
98
|
+
:return:
|
|
99
|
+
A context manager that manages the lifecycle for a :class:`.Signer`.
|
|
100
|
+
"""
|
|
101
|
+
raise NotImplementedError
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
SIGNING_PLUGIN_REGISTRY: List[SigningCommandPlugin] = []
|
|
105
|
+
SIGNING_PLUGIN_ENTRY_POINT_GROUP = 'pyhanko.cli_plugin.signing'
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def register_signing_plugin(cls):
|
|
109
|
+
"""
|
|
110
|
+
Manually put a plugin into the signing plugin registry.
|
|
111
|
+
|
|
112
|
+
:param cls:
|
|
113
|
+
A plugin class.
|
|
114
|
+
:return:
|
|
115
|
+
The same class.
|
|
116
|
+
"""
|
|
117
|
+
SIGNING_PLUGIN_REGISTRY.append(cls())
|
|
118
|
+
return cls
|
pyhanko/cli/py.typed
ADDED
|
File without changes
|
pyhanko/cli/runtime.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from pyhanko.cli.utils import logger
|
|
7
|
+
from pyhanko.config.logging import LogConfig, StdLogOutput
|
|
8
|
+
from pyhanko.pdf_utils import misc
|
|
9
|
+
from pyhanko.pdf_utils.layout import LayoutError
|
|
10
|
+
from pyhanko.sign.general import SigningError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NoStackTraceFormatter(logging.Formatter):
|
|
14
|
+
def formatException(self, ei) -> str:
|
|
15
|
+
return "" # pragma: nocover
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
LOG_FORMAT_STRING = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def logging_setup(log_configs, verbose: bool):
|
|
22
|
+
log_config: LogConfig
|
|
23
|
+
for module, log_config in log_configs.items():
|
|
24
|
+
cur_logger = logging.getLogger(module)
|
|
25
|
+
cur_logger.setLevel(log_config.level)
|
|
26
|
+
handler: logging.StreamHandler
|
|
27
|
+
if isinstance(log_config.output, StdLogOutput):
|
|
28
|
+
if StdLogOutput == StdLogOutput.STDOUT:
|
|
29
|
+
handler = logging.StreamHandler(sys.stdout)
|
|
30
|
+
else:
|
|
31
|
+
handler = logging.StreamHandler()
|
|
32
|
+
# when logging to the console, don't output stack traces
|
|
33
|
+
# unless in verbose mode
|
|
34
|
+
if verbose:
|
|
35
|
+
formatter = logging.Formatter(LOG_FORMAT_STRING)
|
|
36
|
+
else:
|
|
37
|
+
formatter = NoStackTraceFormatter(LOG_FORMAT_STRING)
|
|
38
|
+
else:
|
|
39
|
+
handler = logging.FileHandler(log_config.output)
|
|
40
|
+
formatter = logging.Formatter(LOG_FORMAT_STRING)
|
|
41
|
+
handler.setFormatter(formatter)
|
|
42
|
+
cur_logger.addHandler(handler)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@contextmanager
|
|
46
|
+
def pyhanko_exception_manager():
|
|
47
|
+
msg = exception = None
|
|
48
|
+
try:
|
|
49
|
+
yield
|
|
50
|
+
except click.ClickException:
|
|
51
|
+
raise
|
|
52
|
+
except misc.PdfStrictReadError as e:
|
|
53
|
+
exception = e
|
|
54
|
+
msg = (
|
|
55
|
+
"Failed to read PDF file in strict mode; rerun with "
|
|
56
|
+
"--no-strict-syntax to try again.\n"
|
|
57
|
+
f"Error message: {e.msg}"
|
|
58
|
+
)
|
|
59
|
+
except misc.PdfReadError as e:
|
|
60
|
+
exception = e
|
|
61
|
+
msg = f"Failed to read PDF file: {e.msg}"
|
|
62
|
+
except misc.PdfWriteError as e:
|
|
63
|
+
exception = e
|
|
64
|
+
msg = f"Failed to write PDF file: {e.msg}"
|
|
65
|
+
except SigningError as e:
|
|
66
|
+
exception = e
|
|
67
|
+
msg = f"Error raised while producing signed file: {e.msg}"
|
|
68
|
+
except LayoutError as e:
|
|
69
|
+
exception = e
|
|
70
|
+
msg = f"Error raised while producing signature layout: {e.msg}"
|
|
71
|
+
except Exception as e:
|
|
72
|
+
exception = e
|
|
73
|
+
msg = "Generic processing error."
|
|
74
|
+
|
|
75
|
+
if exception is not None:
|
|
76
|
+
logger.error(msg, exc_info=exception)
|
|
77
|
+
raise click.ClickException(msg)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
DEFAULT_CONFIG_FILE = 'pyhanko.yml'
|
pyhanko/cli/utils.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional, Tuple
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
from pyhanko.sign import fields
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger("cli")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _warn_empty_passphrase():
|
|
11
|
+
click.echo(
|
|
12
|
+
click.style(
|
|
13
|
+
"WARNING: passphrase is empty. If you intended to use an "
|
|
14
|
+
"unencrypted private key, use --no-pass instead.",
|
|
15
|
+
bold=True,
|
|
16
|
+
)
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
readable_file = click.Path(exists=True, readable=True, dir_okay=False)
|
|
21
|
+
writable_file = click.Path(writable=True, dir_okay=False)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _index_page(page):
|
|
25
|
+
try:
|
|
26
|
+
page_ix = int(page)
|
|
27
|
+
if not page_ix:
|
|
28
|
+
raise ValueError
|
|
29
|
+
if page_ix > 0:
|
|
30
|
+
# subtract 1 from the total, since that's what people expect
|
|
31
|
+
# when referring to a page index
|
|
32
|
+
return page_ix - 1
|
|
33
|
+
else:
|
|
34
|
+
# keep negative indexes as-is.
|
|
35
|
+
return page_ix
|
|
36
|
+
except ValueError:
|
|
37
|
+
raise click.ClickException(
|
|
38
|
+
"Sig field parameter PAGE should be a nonzero integer, "
|
|
39
|
+
"not %s." % page
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def parse_field_location_spec(
|
|
44
|
+
spec: str, require_full_spec: bool = True
|
|
45
|
+
) -> Tuple[str, Optional[fields.SigFieldSpec]]:
|
|
46
|
+
try:
|
|
47
|
+
page, box, name = spec.split('/')
|
|
48
|
+
except ValueError:
|
|
49
|
+
if require_full_spec:
|
|
50
|
+
raise click.ClickException(
|
|
51
|
+
"Sig field spec should be of the form PAGE/X1,Y1,X2,Y2/NAME."
|
|
52
|
+
)
|
|
53
|
+
else:
|
|
54
|
+
# interpret the entire string as a field name
|
|
55
|
+
return spec, None
|
|
56
|
+
|
|
57
|
+
page_ix = _index_page(page)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
x1, y1, x2, y2 = map(int, box.split(','))
|
|
61
|
+
except ValueError:
|
|
62
|
+
raise click.ClickException(
|
|
63
|
+
"Sig field parameters X1,Y1,X2,Y2 should be four integers."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return name, fields.SigFieldSpec(
|
|
67
|
+
sig_field_name=name, on_page=page_ix, box=(x1, y1, x2, y2)
|
|
68
|
+
)
|
pyhanko/cli/version.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyhanko-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI tools for stamping and signing PDF files
|
|
5
|
+
Author-email: Matthias Valvekens <dev@mvalvekens.be>
|
|
6
|
+
Maintainer-email: Matthias Valvekens <dev@mvalvekens.be>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/MatthiasValvekens/pyHanko
|
|
9
|
+
Project-URL: Documentation, https://pyhanko.readthedocs.io/
|
|
10
|
+
Project-URL: Changes, https://pyhanko.readthedocs.io/en/latest/changelog.html
|
|
11
|
+
Project-URL: Source Code, https://github.com/MatthiasValvekens/pyHanko
|
|
12
|
+
Project-URL: Issue Tracker, https://github.com/MatthiasValvekens/pyHanko/issues
|
|
13
|
+
Keywords: signature,pdf,pades,digital-signature,pkcs11
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Security :: Cryptography
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: asn1crypto>=1.5.1
|
|
29
|
+
Requires-Dist: tzlocal>=4.3
|
|
30
|
+
Requires-Dist: pyhanko<0.30,>=0.29.0
|
|
31
|
+
Requires-Dist: pyhanko-certvalidator<0.28,>=0.27.0
|
|
32
|
+
Requires-Dist: click<8.2.0,>=8.1.3
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
The lack of open-source CLI tooling to handle digitally signing and stamping PDF files was bothering me, so I went ahead and rolled my own.
|
|
36
|
+
|
|
37
|
+
### Installing
|
|
38
|
+
|
|
39
|
+
PyHanko is hosted on [PyPI](https://pypi.org/project/pyHanko/),
|
|
40
|
+
and can be installed using `pip`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install pyhanko-cli
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Documentation
|
|
47
|
+
|
|
48
|
+
The [documentation for pyHanko is hosted on ReadTheDocs](https://pyhanko.readthedocs.io/en/latest/)
|
|
49
|
+
and includes information on CLI usage, library usage, and API reference documentation derived from
|
|
50
|
+
inline docstrings.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Optional features
|
|
54
|
+
|
|
55
|
+
Optional dependencies are managed at the level of the ``pyhanko`` package.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install 'pyHanko[pkcs11,image-support,opentype,qr]' pyhanko-cli
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Depending on your shell, you might have to leave off the quotes:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install pyHanko[pkcs11,image-support,opentype,qr] pyhanko-cli
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This `pip` invocation includes the optional dependencies required for PKCS#11, image handling,
|
|
68
|
+
OpenType/TrueType support and QR code generation.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
pyhanko/__main__.py,sha256=r_wpx5NBClHu_Vi6IyBsGeo9HZipV73UzPw3u7vEZos,123
|
|
2
|
+
pyhanko/cli/__init__.py,sha256=W-dXL7Ks_h_f83BydK6DO0Xq1z2vXC7imWns9knvgVA,336
|
|
3
|
+
pyhanko/cli/_ctx.py,sha256=57uPbIEnUdIF8Ev3kTs1925h2kXXjMx-tcrgJS3HGUM,2428
|
|
4
|
+
pyhanko/cli/_root.py,sha256=kMMmFcZ3CyjumtVQQG3FG2OWfzl8dL2mpU8hPaglun8,5424
|
|
5
|
+
pyhanko/cli/_trust.py,sha256=Mb3iuM05AnLvQ7fH1df-TOzTaDk430grHOiSxMR2Cvk,5250
|
|
6
|
+
pyhanko/cli/config.py,sha256=TH604IupVilLrj1mhc59dPfRCcjD-c2jb0tMLWlERxA,10059
|
|
7
|
+
pyhanko/cli/plugin_api.py,sha256=ANFvR4XlhTT7Q8V7zEI2PwfsBnhQv3MYGJW6ssvX2L0,3333
|
|
8
|
+
pyhanko/cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
pyhanko/cli/runtime.py,sha256=YIA9KVGFqtOymrGzgaExmmfTd7nNGBNvsMe5H05QSek,2595
|
|
10
|
+
pyhanko/cli/utils.py,sha256=GPDOibQQ2YqPPz7UG9Z7zsOiihJ22a5oM1CF_q49eNE,1854
|
|
11
|
+
pyhanko/cli/version.py,sha256=Y4LHeOXBqKMcOffQfycAar5j-JEc-ObkXZE04PES0Tw,51
|
|
12
|
+
pyhanko/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
pyhanko/cli/commands/crypt.py,sha256=wF7qUabC48f1WiPEXNbrewCdWG4_Yjy3XptbCe9CQv8,7433
|
|
14
|
+
pyhanko/cli/commands/fields.py,sha256=__7BfAbqhYw9Om868mM1NKeaOGzBBx8TejaQ-2g5AiY,2118
|
|
15
|
+
pyhanko/cli/commands/stamp.py,sha256=e321axB3qB48vXtIqyEvjRBVFCiG88joK9fbgUfAwuI,2825
|
|
16
|
+
pyhanko/cli/commands/signing/__init__.py,sha256=Qu72Cu9Z3Zxfyqr9D0Vu0YrtPDxwD6aJWLQRX-4XqP8,9083
|
|
17
|
+
pyhanko/cli/commands/signing/pkcs11_cli.py,sha256=2bn9pQXImL_iSiH2lrDulHyL9aY9m2_V09zoWw_-A8w,5509
|
|
18
|
+
pyhanko/cli/commands/signing/plugin.py,sha256=vSNa6cPHIkF9566t_N7908dp1vxtP3c_yjdvQDcXws8,5515
|
|
19
|
+
pyhanko/cli/commands/signing/simple.py,sha256=_vImPQ9Bx83DdPzCBgU0MhErkCn7m16QhEv78K6t_-M,8600
|
|
20
|
+
pyhanko/cli/commands/signing/utils.py,sha256=gTtqVMbTBWiKOuXm_tTpYu3W4bzsDMiQ9ybfi8l29N8,2054
|
|
21
|
+
pyhanko/cli/commands/validation/__init__.py,sha256=b595plA9s5lCNLb9o25MQ-MMdLZGd0ojxJ0GRTQlAlc,43
|
|
22
|
+
pyhanko/cli/commands/validation/ltv.py,sha256=NNGNq-AgO32e4H8sEe914g2gp4AAsL8P0qKV6xEr4sE,3615
|
|
23
|
+
pyhanko/cli/commands/validation/validate.py,sha256=nqAYXAjgY9vFkZliWAriv_i0H8QRzAmKxb_Q_woDgN0,10875
|
|
24
|
+
pyhanko_cli-0.1.0.dist-info/licenses/LICENSE,sha256=ppfnWrKHvGvEiG2mIZiiuZMKYvGtNMGR9Y1VbYYlwGI,1080
|
|
25
|
+
pyhanko_cli-0.1.0.dist-info/METADATA,sha256=VWRqUyVXnSj_gU9DlhuP6l7wLQ6Ga5pmwDzQaLi3_4Y,2504
|
|
26
|
+
pyhanko_cli-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
27
|
+
pyhanko_cli-0.1.0.dist-info/entry_points.txt,sha256=b0jU5S7K1tkTKcY3pImAO9_bYgha0fr36QZyEb2D8VE,52
|
|
28
|
+
pyhanko_cli-0.1.0.dist-info/top_level.txt,sha256=2Z0D0SOjWu7_9ud976jTS2ZCzzNQlb5QOQ0OVBvZksM,8
|
|
29
|
+
pyhanko_cli-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2023 Matthias Valvekens
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyhanko
|