aws-chain-secrets 1.0.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Hyouk Oh
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,133 @@
1
+ Metadata-Version: 2.1
2
+ Name: aws_chain_secrets
3
+ Version: 1.0.0
4
+ Summary: This aims to enable the use of one or more secrets from AWS SecretsManager.
5
+ Home-page: https://github.com/h5kure/aws-chain-secrets
6
+ Author: Hyouk Oh
7
+ Author-email: h.5.kure@gmail.com
8
+ Classifier: Programming Language :: Python :: 3.7
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.7
16
+ Description-Content-Type: text/x-rst
17
+ License-File: LICENSE
18
+
19
+ AWS chain secrets
20
+ ===================
21
+
22
+ This package aims to make using AWS SecretsManager more comfortable.
23
+
24
+ Introduce
25
+ ---------
26
+ This aims to enable the use of one or more secrets from AWS SecretsManager.
27
+
28
+ If more than one secret is used, the secret specified last takes precedence.
29
+
30
+ For example, if you use secrets named A and B in that order, overlapping entries from A and B will later use
31
+ the value of the specified B entry.
32
+
33
+
34
+ .. code-block:: python
35
+
36
+ >>> A = {"foo": 1, "bar": 2}
37
+ >>> B = {"bar": 3}
38
+ >>> secrets("bar", casting_type=int)
39
+ 3
40
+
41
+ Install
42
+ -------
43
+
44
+ .. code-block:: bash
45
+
46
+ $ python -m pip install aws_chain_secrets
47
+
48
+
49
+ How to use
50
+ ----------
51
+
52
+ .. note::
53
+
54
+ AWS credential is required.
55
+
56
+ If your credentials installed or set to environment, you can omit credentials when initialize `SecretsManager`.
57
+
58
+ connect and fetch manually
59
+ """"""""""""""""""""""""""
60
+
61
+ .. code-block:: python
62
+
63
+ from aws_chain_secrets import SecretsManager
64
+ secrets = SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...)
65
+ secrets.connect()
66
+ secrets.fetch()
67
+ secrets(key="A", default=None, casting_type=int)
68
+ secrets.disconnect()
69
+
70
+
71
+ .. note::
72
+
73
+ The secret assigned last takes precedence over secrets assigned earlier.
74
+
75
+ In this case, `secret_name_2` has a higher priority than `secret_name_1`.
76
+
77
+ This works likes `dict.update` (`secret_name_1.update(secret_name_2)`).
78
+
79
+ use with context manager
80
+ """"""""""""""""""""""""
81
+
82
+ You can omit `connect()`, `fetch()` and `disconnect()` when using context manager.
83
+
84
+ .. code-block:: python
85
+
86
+ from aws_chain_secrets import SecretsManager
87
+ with SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...) as secrets:
88
+ secrets(key="A", default=None, casting_type=int)
89
+
90
+ type casting
91
+ """"""""""""
92
+
93
+ All secret values ​​retrieved from AWS SecretsManager are string types by default.
94
+
95
+ You can change it to any type you want.
96
+
97
+ .. code-block:: python
98
+
99
+ >>> secrets(key="A", casting_type=int)
100
+ 1
101
+ >>> secrets(key="SOME_ARRAY", casting_type=list)
102
+ ['1', '2', '3', '4']
103
+ >>> secrets(key="SOME_ARRAY", casting_type=list[int])
104
+ [1, 2, 3, 4]
105
+
106
+ default value
107
+ """""""""""""
108
+
109
+ You can specify a default value, just like when using Python `dict`'s `get`.
110
+
111
+ .. code-block:: python
112
+
113
+ # if the key value of A does not exist, 0 specified as default is returned.
114
+ >>> secrets(key="A", default=0)
115
+ 0
116
+
117
+ change value
118
+ """"""""""""
119
+
120
+ You can change (or add) the value of a specified secret by name.
121
+
122
+ .. code-block:: python
123
+
124
+ >>> secrets.set('secret_name_1', 'key', 'value')
125
+
126
+ update remote (AWS secrets manager) data from local
127
+ """""""""""""""""""""""""""""""""""""""""""""""""""
128
+
129
+ You can update (upload) the values of a specified secret by name from local to remote.
130
+
131
+ .. code-block:: python
132
+
133
+ >>> secrets.update('secret_name_1')
@@ -0,0 +1,115 @@
1
+ AWS chain secrets
2
+ ===================
3
+
4
+ This package aims to make using AWS SecretsManager more comfortable.
5
+
6
+ Introduce
7
+ ---------
8
+ This aims to enable the use of one or more secrets from AWS SecretsManager.
9
+
10
+ If more than one secret is used, the secret specified last takes precedence.
11
+
12
+ For example, if you use secrets named A and B in that order, overlapping entries from A and B will later use
13
+ the value of the specified B entry.
14
+
15
+
16
+ .. code-block:: python
17
+
18
+ >>> A = {"foo": 1, "bar": 2}
19
+ >>> B = {"bar": 3}
20
+ >>> secrets("bar", casting_type=int)
21
+ 3
22
+
23
+ Install
24
+ -------
25
+
26
+ .. code-block:: bash
27
+
28
+ $ python -m pip install aws_chain_secrets
29
+
30
+
31
+ How to use
32
+ ----------
33
+
34
+ .. note::
35
+
36
+ AWS credential is required.
37
+
38
+ If your credentials installed or set to environment, you can omit credentials when initialize `SecretsManager`.
39
+
40
+ connect and fetch manually
41
+ """"""""""""""""""""""""""
42
+
43
+ .. code-block:: python
44
+
45
+ from aws_chain_secrets import SecretsManager
46
+ secrets = SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...)
47
+ secrets.connect()
48
+ secrets.fetch()
49
+ secrets(key="A", default=None, casting_type=int)
50
+ secrets.disconnect()
51
+
52
+
53
+ .. note::
54
+
55
+ The secret assigned last takes precedence over secrets assigned earlier.
56
+
57
+ In this case, `secret_name_2` has a higher priority than `secret_name_1`.
58
+
59
+ This works likes `dict.update` (`secret_name_1.update(secret_name_2)`).
60
+
61
+ use with context manager
62
+ """"""""""""""""""""""""
63
+
64
+ You can omit `connect()`, `fetch()` and `disconnect()` when using context manager.
65
+
66
+ .. code-block:: python
67
+
68
+ from aws_chain_secrets import SecretsManager
69
+ with SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...) as secrets:
70
+ secrets(key="A", default=None, casting_type=int)
71
+
72
+ type casting
73
+ """"""""""""
74
+
75
+ All secret values ​​retrieved from AWS SecretsManager are string types by default.
76
+
77
+ You can change it to any type you want.
78
+
79
+ .. code-block:: python
80
+
81
+ >>> secrets(key="A", casting_type=int)
82
+ 1
83
+ >>> secrets(key="SOME_ARRAY", casting_type=list)
84
+ ['1', '2', '3', '4']
85
+ >>> secrets(key="SOME_ARRAY", casting_type=list[int])
86
+ [1, 2, 3, 4]
87
+
88
+ default value
89
+ """""""""""""
90
+
91
+ You can specify a default value, just like when using Python `dict`'s `get`.
92
+
93
+ .. code-block:: python
94
+
95
+ # if the key value of A does not exist, 0 specified as default is returned.
96
+ >>> secrets(key="A", default=0)
97
+ 0
98
+
99
+ change value
100
+ """"""""""""
101
+
102
+ You can change (or add) the value of a specified secret by name.
103
+
104
+ .. code-block:: python
105
+
106
+ >>> secrets.set('secret_name_1', 'key', 'value')
107
+
108
+ update remote (AWS secrets manager) data from local
109
+ """""""""""""""""""""""""""""""""""""""""""""""""""
110
+
111
+ You can update (upload) the values of a specified secret by name from local to remote.
112
+
113
+ .. code-block:: python
114
+
115
+ >>> secrets.update('secret_name_1')
@@ -0,0 +1 @@
1
+ from .secrets_manager import SecretsManager
@@ -0,0 +1,67 @@
1
+ import json
2
+ import string
3
+ from dataclasses import dataclass
4
+ from types import GenericAlias
5
+ from typing import Any, Type, get_origin, get_args
6
+
7
+ TRUE_STRINGS = ('y', 'yes', 't', 'true', 'on', '1')
8
+ FALSE_STRINGS = ('', 'n', 'no', 'f', 'false', 'off', '0')
9
+
10
+
11
+ def string_to_boolean(value: str) -> bool:
12
+ """
13
+ Convert a string representation of truth to True or False.
14
+
15
+ :param value: a string representation of truth
16
+ :return: True if value represents truth, False if value represents false, otherwise raise ValueError
17
+ :raises: Raises ValueError if 'value' is anything else
18
+ """
19
+ value = value.lower()
20
+ if value in TRUE_STRINGS:
21
+ return True
22
+ if value in FALSE_STRINGS:
23
+ return False
24
+ raise ValueError(f"invalid truth value {repr(value)}")
25
+
26
+
27
+ def cast_boolean(value: Any) -> bool:
28
+ value = str(value)
29
+ return string_to_boolean(value)
30
+
31
+
32
+ def cast(value: str, casting_type: Type = None) -> Any:
33
+ """
34
+ string value to typed value
35
+ :param value: original string
36
+ :param casting_type: expected type to be
37
+ :return: typed value
38
+ """
39
+ if casting_type is None:
40
+ return value
41
+ if casting_type is bool:
42
+ return cast_boolean(value)
43
+ if casting_type in (set, list, tuple, bytes, bytearray):
44
+ return Sequence(wrapper=casting_type)(value)
45
+ if casting_type is dict:
46
+ return json.loads(value)
47
+ if isinstance(casting_type, GenericAlias):
48
+ origin = get_origin(casting_type)
49
+ args = get_args(casting_type)
50
+ if origin in (set, list, tuple, bytes, bytearray):
51
+ return Sequence(cast_type=args[0] if args else str, wrapper=origin)(value)
52
+ raise NotImplementedError(f"cannot cast to {repr(casting_type)}")
53
+ return casting_type(value)
54
+
55
+
56
+ @dataclass
57
+ class Sequence:
58
+ """
59
+ Helper to cast Sequence (list, tuple, bytes, bytearray) and Set(set, frozenset)
60
+ """
61
+ cast_type: Type = str
62
+ delimiter: str = ','
63
+ strip: str = string.whitespace
64
+ wrapper: Type = list
65
+
66
+ def __call__(self, value: str):
67
+ return self.wrapper(cast(v.strip(self.strip), self.cast_type) for v in value.split(self.delimiter))
@@ -0,0 +1,44 @@
1
+ from typing import Optional
2
+
3
+ import boto3
4
+ from botocore.client import BaseClient
5
+
6
+
7
+ class Client:
8
+ """
9
+ wrapper for AWS client
10
+ """
11
+ def __init__(
12
+ self,
13
+ service_name: str,
14
+ region_name: str,
15
+ aws_access_key_id: str = None,
16
+ aws_secret_access_key: str = None
17
+ ):
18
+ self.service_name = service_name
19
+ self.region_name = region_name
20
+ self.aws_access_key_id = aws_access_key_id
21
+ self.aws_secret_access_key = aws_secret_access_key
22
+ self._client: Optional[BaseClient] = None
23
+
24
+ def __enter__(self):
25
+ self.connect()
26
+ return self
27
+
28
+ def __exit__(self, exc_type, exc_val, exc_tb):
29
+ self.disconnect()
30
+
31
+ def _create_client(self) -> BaseClient:
32
+ return boto3.session.Session().client(
33
+ service_name=self.service_name,
34
+ region_name=self.region_name,
35
+ aws_access_key_id=self.aws_access_key_id,
36
+ aws_secret_access_key=self.aws_secret_access_key
37
+ )
38
+
39
+ def connect(self):
40
+ self._client = self._create_client()
41
+
42
+ def disconnect(self):
43
+ self._client.close()
44
+ del self._client
@@ -0,0 +1,42 @@
1
+
2
+
3
+ class SecretsManagerException(Exception):
4
+ DEFAULT_MESSAGE = "Unknown error occurred."
5
+
6
+ def __init__(self, message: str = None):
7
+ super().__init__(message or self.DEFAULT_MESSAGE)
8
+
9
+ @classmethod
10
+ def from_code(cls, code: str, message: str = None) -> 'SecretsManagerException':
11
+ if code == 'DecryptionFailureException':
12
+ return DecryptionFailureException(message)
13
+ elif code == 'InternalServiceErrorException':
14
+ return InternalServiceErrorException(message)
15
+ elif code == 'InvalidParameterException':
16
+ return InvalidParameterException(message)
17
+ elif code == 'InvalidRequestException':
18
+ return InvalidRequestException(message)
19
+ elif code == 'ResourceNotFoundException':
20
+ return ResourceNotFoundException(message)
21
+ else:
22
+ return cls(message)
23
+
24
+
25
+ class DecryptionFailureException(SecretsManagerException):
26
+ DEFAULT_MESSAGE = "Secrets Manager can't decrypt the protected secret text using the provided KMS key."
27
+
28
+
29
+ class InternalServiceErrorException(SecretsManagerException):
30
+ DEFAULT_MESSAGE = "An error occurred on the server side."
31
+
32
+
33
+ class InvalidParameterException(SecretsManagerException):
34
+ DEFAULT_MESSAGE = "You provided an invalid value for a parameter.",
35
+
36
+
37
+ class InvalidRequestException(SecretsManagerException):
38
+ DEFAULT_MESSAGE = "You provided a parameter value that is not valid for the current state of the resource."
39
+
40
+
41
+ class ResourceNotFoundException(SecretsManagerException):
42
+ DEFAULT_MESSAGE = "We can't find the resource that you asked for."
File without changes
@@ -0,0 +1,117 @@
1
+ import base64
2
+ import json
3
+ from collections import ChainMap
4
+ from typing import Any, Type
5
+
6
+ from botocore.exceptions import ClientError
7
+
8
+ from aws_chain_secrets.caster import cast
9
+ from aws_chain_secrets.client import Client
10
+ from aws_chain_secrets.exceptions import SecretsManagerException
11
+
12
+
13
+ class Null:
14
+ """
15
+ class to represent null type
16
+ """
17
+ pass
18
+
19
+
20
+ null = Null()
21
+
22
+
23
+ class SecretsManager(Client):
24
+ def __init__(
25
+ self,
26
+ region_name: str,
27
+ *secret_names: str,
28
+ aws_access_key_id: str = None,
29
+ aws_secret_access_key: str = None
30
+ ):
31
+ """
32
+ initial setup
33
+ :param region_name: AWS region name
34
+ :param secret_names: These are the secret names from which to read settings. The last name has priority.
35
+ """
36
+ self.secret_names = secret_names
37
+ super().__init__(
38
+ "secretsmanager",
39
+ region_name,
40
+ aws_access_key_id,
41
+ aws_secret_access_key
42
+ )
43
+ self._secrets = {secret_name: {} for secret_name in secret_names}
44
+ self._combined = ChainMap(*reversed(self._secrets.values()))
45
+
46
+ def __call__(self, key, *, default: Any = null, casting_type: Type = str):
47
+ return self.get(key, default=default, casting_type=casting_type)
48
+
49
+ def __enter__(self):
50
+ super().__enter__()
51
+ self.fetch()
52
+ return self
53
+
54
+ def get(self, key, *, default: Any = null, casting_type: Type = str):
55
+ """
56
+ get secret value
57
+ :param key: key value to search
58
+ :param default: default value if key not exists in secrets
59
+ :param casting_type: casting type to convert value
60
+ :return: Any secret value specified by key
61
+ """
62
+ try:
63
+ value = self._combined[key]
64
+ except KeyError:
65
+ if isinstance(default, Null):
66
+ raise KeyError(f"{repr(key)} not found. Please check secret value in AWS Secrets Manager.")
67
+ return default
68
+ return cast(value, casting_type)
69
+
70
+ def set(self, secret_name: str, key, value):
71
+ """
72
+ set a `key: value` to the specified secret
73
+ :param secret_name: secret_name of AWS Secrets Manager
74
+ :param key: key of map
75
+ :param value: value of map
76
+ """
77
+ self._secrets[secret_name][key] = value
78
+
79
+ def keys(self):
80
+ return self._combined.keys()
81
+
82
+ def values(self):
83
+ return self._combined.values()
84
+
85
+ def items(self):
86
+ return self._combined.items()
87
+
88
+ def fetch(self):
89
+ """
90
+ get secrets from AWS and update
91
+ """
92
+ for secret_name in self.secret_names:
93
+ self._secrets[secret_name].clear()
94
+ self._secrets[secret_name].update(self._get_secrets(secret_name))
95
+
96
+ def update(self, secret_name: str):
97
+ """
98
+ update specified secrets from local to AWS
99
+ :param secret_name: secret name of AWS Secrets Manager
100
+ """
101
+ self._client.update_secret(SecretId=secret_name, SecretString=json.dumps(self._secrets[secret_name]))
102
+
103
+ def _get_secrets(self, secret_name: str) -> dict:
104
+ """
105
+ get secrets from AWS
106
+ :param secret_name: secret name of AWS Secrets Manager
107
+ """
108
+ try:
109
+ response = self._client.get_secret_value(SecretId=secret_name)
110
+ except ClientError as e:
111
+ raise SecretsManagerException.from_code(e.response['Error']['Code'])
112
+ else:
113
+ if 'SecretString' in response:
114
+ return json.loads(response['SecretString'])
115
+ return json.loads(base64.b64decode(response['SecretBinary']))
116
+
117
+
@@ -0,0 +1,133 @@
1
+ Metadata-Version: 2.1
2
+ Name: aws-chain-secrets
3
+ Version: 1.0.0
4
+ Summary: This aims to enable the use of one or more secrets from AWS SecretsManager.
5
+ Home-page: https://github.com/h5kure/aws-chain-secrets
6
+ Author: Hyouk Oh
7
+ Author-email: h.5.kure@gmail.com
8
+ Classifier: Programming Language :: Python :: 3.7
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.7
16
+ Description-Content-Type: text/x-rst
17
+ License-File: LICENSE
18
+
19
+ AWS chain secrets
20
+ ===================
21
+
22
+ This package aims to make using AWS SecretsManager more comfortable.
23
+
24
+ Introduce
25
+ ---------
26
+ This aims to enable the use of one or more secrets from AWS SecretsManager.
27
+
28
+ If more than one secret is used, the secret specified last takes precedence.
29
+
30
+ For example, if you use secrets named A and B in that order, overlapping entries from A and B will later use
31
+ the value of the specified B entry.
32
+
33
+
34
+ .. code-block:: python
35
+
36
+ >>> A = {"foo": 1, "bar": 2}
37
+ >>> B = {"bar": 3}
38
+ >>> secrets("bar", casting_type=int)
39
+ 3
40
+
41
+ Install
42
+ -------
43
+
44
+ .. code-block:: bash
45
+
46
+ $ python -m pip install aws_chain_secrets
47
+
48
+
49
+ How to use
50
+ ----------
51
+
52
+ .. note::
53
+
54
+ AWS credential is required.
55
+
56
+ If your credentials installed or set to environment, you can omit credentials when initialize `SecretsManager`.
57
+
58
+ connect and fetch manually
59
+ """"""""""""""""""""""""""
60
+
61
+ .. code-block:: python
62
+
63
+ from aws_chain_secrets import SecretsManager
64
+ secrets = SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...)
65
+ secrets.connect()
66
+ secrets.fetch()
67
+ secrets(key="A", default=None, casting_type=int)
68
+ secrets.disconnect()
69
+
70
+
71
+ .. note::
72
+
73
+ The secret assigned last takes precedence over secrets assigned earlier.
74
+
75
+ In this case, `secret_name_2` has a higher priority than `secret_name_1`.
76
+
77
+ This works likes `dict.update` (`secret_name_1.update(secret_name_2)`).
78
+
79
+ use with context manager
80
+ """"""""""""""""""""""""
81
+
82
+ You can omit `connect()`, `fetch()` and `disconnect()` when using context manager.
83
+
84
+ .. code-block:: python
85
+
86
+ from aws_chain_secrets import SecretsManager
87
+ with SecretsManager('ap-northeast-2', 'secret_name_1', 'secret_name_2', ...) as secrets:
88
+ secrets(key="A", default=None, casting_type=int)
89
+
90
+ type casting
91
+ """"""""""""
92
+
93
+ All secret values ​​retrieved from AWS SecretsManager are string types by default.
94
+
95
+ You can change it to any type you want.
96
+
97
+ .. code-block:: python
98
+
99
+ >>> secrets(key="A", casting_type=int)
100
+ 1
101
+ >>> secrets(key="SOME_ARRAY", casting_type=list)
102
+ ['1', '2', '3', '4']
103
+ >>> secrets(key="SOME_ARRAY", casting_type=list[int])
104
+ [1, 2, 3, 4]
105
+
106
+ default value
107
+ """""""""""""
108
+
109
+ You can specify a default value, just like when using Python `dict`'s `get`.
110
+
111
+ .. code-block:: python
112
+
113
+ # if the key value of A does not exist, 0 specified as default is returned.
114
+ >>> secrets(key="A", default=0)
115
+ 0
116
+
117
+ change value
118
+ """"""""""""
119
+
120
+ You can change (or add) the value of a specified secret by name.
121
+
122
+ .. code-block:: python
123
+
124
+ >>> secrets.set('secret_name_1', 'key', 'value')
125
+
126
+ update remote (AWS secrets manager) data from local
127
+ """""""""""""""""""""""""""""""""""""""""""""""""""
128
+
129
+ You can update (upload) the values of a specified secret by name from local to remote.
130
+
131
+ .. code-block:: python
132
+
133
+ >>> secrets.update('secret_name_1')
@@ -0,0 +1,16 @@
1
+ LICENSE
2
+ README.rst
3
+ setup.py
4
+ aws_chain_secrets/__init__.py
5
+ aws_chain_secrets/caster.py
6
+ aws_chain_secrets/client.py
7
+ aws_chain_secrets/exceptions.py
8
+ aws_chain_secrets/py.typed
9
+ aws_chain_secrets/secrets_manager.py
10
+ aws_chain_secrets.egg-info/PKG-INFO
11
+ aws_chain_secrets.egg-info/SOURCES.txt
12
+ aws_chain_secrets.egg-info/dependency_links.txt
13
+ aws_chain_secrets.egg-info/requires.txt
14
+ aws_chain_secrets.egg-info/top_level.txt
15
+ tests/__init__.py
16
+ tests/test_caster.py
@@ -0,0 +1,2 @@
1
+ aws_chain_secrets
2
+ tests
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,29 @@
1
+ import setuptools
2
+
3
+ with open("README.rst", "r", encoding='utf-8') as readme:
4
+ long_description = readme.read()
5
+
6
+ setuptools.setup(
7
+ name="aws_chain_secrets",
8
+ version='1.0.0',
9
+ author="Hyouk Oh",
10
+ author_email="h.5.kure@gmail.com",
11
+ description="This aims to enable the use of one or more secrets from AWS SecretsManager.",
12
+ long_description=long_description,
13
+ long_description_content_type="text/x-rst",
14
+ url="https://github.com/h5kure/aws-chain-secrets",
15
+ packages=setuptools.find_packages(),
16
+ package_data={"": ["py.typed"]},
17
+ include_package_data=True,
18
+ classifiers=[
19
+ "Programming Language :: Python :: 3.7",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "License :: OSI Approved :: MIT License",
25
+ "Operating System :: OS Independent",
26
+ ],
27
+ python_requires='>=3.7',
28
+ install_requires=['boto3']
29
+ )
File without changes
@@ -0,0 +1,21 @@
1
+ import unittest
2
+
3
+ from aws_chain_secrets import caster
4
+
5
+
6
+ class CasterTestCase(unittest.TestCase):
7
+ def test_int(self):
8
+ self.assertEqual(1, caster.cast('1', int))
9
+
10
+ def test_bool(self):
11
+ self.assertTrue(caster.cast('true', bool))
12
+
13
+ def test_list(self):
14
+ self.assertEqual(['1', '2', '3', '4'], caster.cast('1,2,3,4', list))
15
+ self.assertEqual([1, 2, 3, 4], caster.cast('1, 2, 3, 4', list[int]))
16
+
17
+ def test_set(self):
18
+ self.assertEqual({1, 2, 3, 4}, caster.cast('1,2,3,4', set[int]))
19
+
20
+ def test_dict(self):
21
+ self.assertEqual({'foo': 'bar'}, caster.cast('{"foo": "bar"}', dict))