devopsdriver 0.1.35__tar.gz → 0.1.36__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.
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/PKG-INFO +2 -2
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/README.md +1 -1
- devopsdriver-0.1.36/devopsdriver/__init__.py +9 -0
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/clients.py +1 -1
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/client.py +2 -2
- devopsdriver-0.1.36/devopsdriver/sendmail.py +88 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver/settings.py +10 -3
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver.egg-info/PKG-INFO +2 -2
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver.egg-info/SOURCES.txt +8 -6
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/tests/test_azure_clients.py +1 -1
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/tests/test_azure_workitem.py +1 -1
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/tests/test_azure_workitem_client.py +2 -2
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/tests/test_azure_workitem_wiql.py +5 -5
- devopsdriver-0.1.36/tests/test_sendmail.py +151 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/tests/test_settings.py +18 -20
- devopsdriver-0.1.35/devopsdriver/__init__.py +0 -7
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/LICENSE +0 -0
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/__init__.py +0 -0
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/__init__.py +0 -0
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/wiql.py +0 -0
- {devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/workitem.py +0 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver.egg-info/dependency_links.txt +0 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver.egg-info/requires.txt +0 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/devopsdriver.egg-info/top_level.txt +0 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/pyproject.toml +0 -0
- {devopsdriver-0.1.35 → devopsdriver-0.1.36}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devopsdriver
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.36
|
|
4
4
|
Summary: DevOps tools
|
|
5
5
|
Author-email: Marc Page <marcallenpage@gmail.com>
|
|
6
6
|
License: This is free and unencumbered software released into the public domain.
|
|
@@ -52,7 +52,7 @@ Requires-Dist: setuptools==69.0.2
|
|
|
52
52
|
Requires-Dist: azure-devops==7.1.0b4
|
|
53
53
|
|
|
54
54
|

|
|
55
|
-
[](https://pypi.org/project/devopsdriver/0.1.36/)
|
|
56
56
|
[](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
|
|
57
57
|
[](https://github.com/marcpage/devops-driver/graphs/contributors)
|
|
58
58
|
[](http://makeapullrequest.com)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|

|
|
2
|
-
[](https://pypi.org/project/devopsdriver/0.1.36/)
|
|
3
3
|
[](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
|
|
4
4
|
[](https://github.com/marcpage/devops-driver/graphs/contributors)
|
|
5
5
|
[](http://makeapullrequest.com)
|
|
@@ -11,7 +11,7 @@ from azure.devops.connection import Connection as AzureConnection
|
|
|
11
11
|
from msrest.authentication import BasicAuthentication as MSBasicAuthentication
|
|
12
12
|
|
|
13
13
|
from devopsdriver.settings import Settings
|
|
14
|
-
from devopsdriver.
|
|
14
|
+
from devopsdriver.azdo.workitem.client import Client as WIClient
|
|
15
15
|
|
|
16
16
|
CONNECTION = AzureConnection
|
|
17
17
|
AUTHENTICATION = MSBasicAuthentication
|
{devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/client.py
RENAMED
|
@@ -6,8 +6,8 @@ from azure.devops.v7_1.work_item_tracking.models import Wiql as AzureWiql
|
|
|
6
6
|
from azure.devops.v7_1.work_item_tracking.models import WorkItem as AzureWorkItem
|
|
7
7
|
from azure.devops.v7_1.work_item_tracking.models import TeamContext
|
|
8
8
|
from azure.devops.v7_1.work_item_tracking.models import WorkItemQueryResult
|
|
9
|
-
from devopsdriver.
|
|
10
|
-
from devopsdriver.
|
|
9
|
+
from devopsdriver.azdo.workitem import WorkItem
|
|
10
|
+
from devopsdriver.azdo.workitem.wiql import Wiql
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Client:
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
""" Ability to send emails with embedded images """
|
|
4
|
+
from smtplib import SMTP as OS_SMTP, SMTP_SSL as OS_SMTP_SSL
|
|
5
|
+
from email.mime.multipart import MIMEMultipart as OS_MIMEMultipart
|
|
6
|
+
from email.mime.text import MIMEText as OS_MIMEText
|
|
7
|
+
from email.mime.image import MIMEImage as OS_MIMEImage
|
|
8
|
+
|
|
9
|
+
from devopsdriver.settings import Settings
|
|
10
|
+
|
|
11
|
+
IMAGE_HEADERS = {".png": b"\x89PNG\r\n\x1a\n", ".jpg": b"\xff\xd8\xff"}
|
|
12
|
+
|
|
13
|
+
# for testing
|
|
14
|
+
MIMEMULTIPART = OS_MIMEMultipart
|
|
15
|
+
MIMETEXT = OS_MIMEText
|
|
16
|
+
MIMEIMAGE = OS_MIMEImage
|
|
17
|
+
SMTP = OS_SMTP
|
|
18
|
+
SMTPSSL = OS_SMTP_SSL
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def image_extension(data: bytes) -> str:
|
|
22
|
+
"""Given image data, determine the file extension
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
data (bytes): The image binary data
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
AttributeError: If the data type is not recognized
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
str: The extension, like ".png"
|
|
32
|
+
"""
|
|
33
|
+
for extension, header in IMAGE_HEADERS.items():
|
|
34
|
+
if data.startswith(header):
|
|
35
|
+
return extension
|
|
36
|
+
|
|
37
|
+
raise AttributeError("Image not a known format: " + ",".join(IMAGE_HEADERS))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def send_email(
|
|
41
|
+
recipients: str | list[str],
|
|
42
|
+
subject: str,
|
|
43
|
+
html_body: str,
|
|
44
|
+
settings: Settings = None,
|
|
45
|
+
**image_data,
|
|
46
|
+
):
|
|
47
|
+
"""Sends an email with embedded images
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
recipients (str | list[str]): A single email address or a list of them
|
|
51
|
+
subject (str): Subject line
|
|
52
|
+
html_body (str): html formatted body. To reference an image in your
|
|
53
|
+
body, <img src="cid:image1"> if you pass image1=png.read()
|
|
54
|
+
settings (Settings, optional): The settings object. Defaults to None.
|
|
55
|
+
image_data (dict, optional): keyword image names to binary image data
|
|
56
|
+
"""
|
|
57
|
+
settings = Settings(__file__).key("secrets") if settings is None else settings
|
|
58
|
+
required = {"smtp.sender", "smtp.server", "smtp.port", "smtp.password"}
|
|
59
|
+
missing = {r for r in required if r not in settings}
|
|
60
|
+
assert not missing, (
|
|
61
|
+
", ".join(missing) + " not found in:\n" + "\n".join(settings.search_files)
|
|
62
|
+
)
|
|
63
|
+
sender = settings["smtp.sender"]
|
|
64
|
+
username = settings.get("smtp.username", sender)
|
|
65
|
+
message = MIMEMULTIPART()
|
|
66
|
+
message["Subject"] = subject
|
|
67
|
+
message["From"] = sender
|
|
68
|
+
message["To"] = ", ".join(
|
|
69
|
+
[recipients] if isinstance(recipients, str) else recipients
|
|
70
|
+
)
|
|
71
|
+
message.attach(MIMETEXT(html_body, "html"))
|
|
72
|
+
connection_type = SMTPSSL if settings.get("smtp.ssl", True) else SMTP
|
|
73
|
+
|
|
74
|
+
for name, binary_data in image_data.items():
|
|
75
|
+
image = MIMEIMAGE(binary_data)
|
|
76
|
+
image.add_header("Content-ID", f"<{name}>")
|
|
77
|
+
image.add_header(
|
|
78
|
+
"Content-Disposition",
|
|
79
|
+
"inline",
|
|
80
|
+
filename=name + image_extension(binary_data),
|
|
81
|
+
)
|
|
82
|
+
message.attach(image)
|
|
83
|
+
|
|
84
|
+
with connection_type(settings["smtp.server"], settings["smtp.port"]) as smtp:
|
|
85
|
+
smtp.set_debuglevel(False)
|
|
86
|
+
smtp.login(username, settings["smtp.password"])
|
|
87
|
+
smtp.sendmail(sender, recipients, message.as_string())
|
|
88
|
+
smtp.quit()
|
|
@@ -361,10 +361,17 @@ class Settings:
|
|
|
361
361
|
|
|
362
362
|
def main() -> None:
|
|
363
363
|
"""Get settings values"""
|
|
364
|
-
settings = Settings(__file__, dirname(dirname(__file__))).key("secrets")
|
|
365
|
-
|
|
366
364
|
args = list(ARGV[1:])
|
|
367
365
|
|
|
366
|
+
if not args or "--help" in args or "-h" in args:
|
|
367
|
+
PRINT("pass in settings to see if they are set and to what value")
|
|
368
|
+
PRINT("You can pass dotted names to get inner values, like smpt.server")
|
|
369
|
+
PRINT("You can pass --secrets to set keychain values that have not been set")
|
|
370
|
+
PRINT("You can also pass --help or -h to get this message")
|
|
371
|
+
return
|
|
372
|
+
|
|
373
|
+
settings = Settings(__file__, dirname(dirname(__file__))).key("secrets")
|
|
374
|
+
|
|
368
375
|
if "--secrets" in args:
|
|
369
376
|
args.remove("--secrets")
|
|
370
377
|
|
|
@@ -380,7 +387,7 @@ def main() -> None:
|
|
|
380
387
|
PRINT("\tValue set")
|
|
381
388
|
|
|
382
389
|
for arg in args:
|
|
383
|
-
PRINT(settings.get(arg))
|
|
390
|
+
PRINT(f"{settings.get(arg)}")
|
|
384
391
|
|
|
385
392
|
|
|
386
393
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devopsdriver
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.36
|
|
4
4
|
Summary: DevOps tools
|
|
5
5
|
Author-email: Marc Page <marcallenpage@gmail.com>
|
|
6
6
|
License: This is free and unencumbered software released into the public domain.
|
|
@@ -52,7 +52,7 @@ Requires-Dist: setuptools==69.0.2
|
|
|
52
52
|
Requires-Dist: azure-devops==7.1.0b4
|
|
53
53
|
|
|
54
54
|

|
|
55
|
-
[](https://pypi.org/project/devopsdriver/0.1.36/)
|
|
56
56
|
[](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
|
|
57
57
|
[](https://github.com/marcpage/devops-driver/graphs/contributors)
|
|
58
58
|
[](http://makeapullrequest.com)
|
|
@@ -2,20 +2,22 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
devopsdriver/__init__.py
|
|
5
|
+
devopsdriver/sendmail.py
|
|
5
6
|
devopsdriver/settings.py
|
|
6
7
|
devopsdriver.egg-info/PKG-INFO
|
|
7
8
|
devopsdriver.egg-info/SOURCES.txt
|
|
8
9
|
devopsdriver.egg-info/dependency_links.txt
|
|
9
10
|
devopsdriver.egg-info/requires.txt
|
|
10
11
|
devopsdriver.egg-info/top_level.txt
|
|
11
|
-
devopsdriver/
|
|
12
|
-
devopsdriver/
|
|
13
|
-
devopsdriver/
|
|
14
|
-
devopsdriver/
|
|
15
|
-
devopsdriver/
|
|
16
|
-
devopsdriver/
|
|
12
|
+
devopsdriver/azdo/__init__.py
|
|
13
|
+
devopsdriver/azdo/clients.py
|
|
14
|
+
devopsdriver/azdo/workitem/__init__.py
|
|
15
|
+
devopsdriver/azdo/workitem/client.py
|
|
16
|
+
devopsdriver/azdo/workitem/wiql.py
|
|
17
|
+
devopsdriver/azdo/workitem/workitem.py
|
|
17
18
|
tests/test_azure_clients.py
|
|
18
19
|
tests/test_azure_workitem.py
|
|
19
20
|
tests/test_azure_workitem_client.py
|
|
20
21
|
tests/test_azure_workitem_wiql.py
|
|
22
|
+
tests/test_sendmail.py
|
|
21
23
|
tests/test_settings.py
|
|
@@ -11,7 +11,7 @@ from os.path import join
|
|
|
11
11
|
from helpers import setup_settings, write
|
|
12
12
|
|
|
13
13
|
from devopsdriver import Azure
|
|
14
|
-
from devopsdriver.
|
|
14
|
+
from devopsdriver.azdo import clients
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class MockConnection: # pylint: disable=too-few-public-methods
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
from types import SimpleNamespace
|
|
6
6
|
|
|
7
|
-
from devopsdriver.
|
|
8
|
-
from devopsdriver.
|
|
7
|
+
from devopsdriver.azdo.workitem.client import Client
|
|
8
|
+
from devopsdriver.azdo import Wiql, Equal
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class MockClient: # pylint: disable=too-few-public-methods
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
from datetime import date, datetime
|
|
6
6
|
|
|
7
|
-
from devopsdriver.
|
|
8
|
-
from devopsdriver.
|
|
9
|
-
from devopsdriver.
|
|
10
|
-
from devopsdriver.
|
|
11
|
-
from devopsdriver.
|
|
7
|
+
from devopsdriver.azdo import Wiql
|
|
8
|
+
from devopsdriver.azdo import Ascending, Descending, Value
|
|
9
|
+
from devopsdriver.azdo import IsEmpty, IsNotEmpty, And, Or
|
|
10
|
+
from devopsdriver.azdo import GreaterThan, LessThan, Equal, NotEqual
|
|
11
|
+
from devopsdriver.azdo import GreaterThanOrEqual, LessThanOrEqual
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def test_no_params() -> None:
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
""" Test sendmail """
|
|
4
|
+
|
|
5
|
+
from devopsdriver import sendmail # for debugging
|
|
6
|
+
from devopsdriver import send_email
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MockMultipart(dict):
|
|
10
|
+
"""Mock mime multipart"""
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.objects = []
|
|
14
|
+
super().__init__()
|
|
15
|
+
|
|
16
|
+
def attach(self, thing):
|
|
17
|
+
"""mock attaching"""
|
|
18
|
+
self.objects.append(thing)
|
|
19
|
+
|
|
20
|
+
def as_string(self) -> str:
|
|
21
|
+
"""don't actually convert to string so we can check fields"""
|
|
22
|
+
return self
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MockText:
|
|
26
|
+
"""mock mime text"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, text: str, kind: str):
|
|
29
|
+
self.text = text
|
|
30
|
+
self.kind = kind
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MockImage:
|
|
34
|
+
"""mock mime image"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, data: bytes):
|
|
37
|
+
self.data = data
|
|
38
|
+
self.headers = {}
|
|
39
|
+
self.filenames = {}
|
|
40
|
+
|
|
41
|
+
def add_header(self, key, value, filename=None):
|
|
42
|
+
"""store headers and filenames (if they have them)"""
|
|
43
|
+
self.headers[key] = value
|
|
44
|
+
|
|
45
|
+
if filename:
|
|
46
|
+
self.filenames[key] = filename
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class MockSmtp:
|
|
50
|
+
"""mock smtp and smpt_ssl"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, server: str, port: int):
|
|
53
|
+
self.server = server
|
|
54
|
+
self.port = port
|
|
55
|
+
self.debuglevel = None
|
|
56
|
+
self.username = None
|
|
57
|
+
self.password = None
|
|
58
|
+
self.sender = None
|
|
59
|
+
self.recipients = None
|
|
60
|
+
self.message = None
|
|
61
|
+
|
|
62
|
+
def set_debuglevel(self, level: bool):
|
|
63
|
+
"""store that we've set the debug level"""
|
|
64
|
+
self.debuglevel = level
|
|
65
|
+
|
|
66
|
+
def login(self, username: str, password: str):
|
|
67
|
+
"""store the credentials"""
|
|
68
|
+
self.username = username
|
|
69
|
+
self.password = password
|
|
70
|
+
|
|
71
|
+
def sendmail(self, sender: str, recipients: list[str], message: str):
|
|
72
|
+
"""store what we're sending"""
|
|
73
|
+
self.sender = sender
|
|
74
|
+
self.recipients = recipients
|
|
75
|
+
self.message = message
|
|
76
|
+
|
|
77
|
+
def quit(self):
|
|
78
|
+
"""on quit check everything"""
|
|
79
|
+
assert self.server == "smtp.com", self.server
|
|
80
|
+
assert self.port == 1234, self.port
|
|
81
|
+
assert not self.debuglevel and self.debuglevel is not None, self.debuglevel
|
|
82
|
+
assert self.username == "from@domain.com", self.username
|
|
83
|
+
assert self.password == "setec astronomy", self.password
|
|
84
|
+
assert self.sender == "from@domain.com", self.sender
|
|
85
|
+
assert self.recipients == "to@domain.com", self.recipients
|
|
86
|
+
assert len(self.message.objects) == 2, self.message.objects
|
|
87
|
+
assert self.message.objects[0].text == "body", self.message.objects[0].text
|
|
88
|
+
assert self.message.objects[0].kind == "html", self.message.objects[0].kind
|
|
89
|
+
assert (
|
|
90
|
+
self.message.objects[1].data == b"\x89PNG\r\n\x1a\n0000"
|
|
91
|
+
), self.message.objects[1].data
|
|
92
|
+
assert (
|
|
93
|
+
self.message.objects[1].headers["Content-ID"] == "<image1>"
|
|
94
|
+
), self.message.objects[1].headers["Content-ID"]
|
|
95
|
+
assert (
|
|
96
|
+
self.message.objects[1].headers["Content-Disposition"] == "inline"
|
|
97
|
+
), self.message.objects[1].headers["Content-Disposition"]
|
|
98
|
+
assert (
|
|
99
|
+
self.message.objects[1].filenames["Content-Disposition"] == "image1.png"
|
|
100
|
+
), self.message.objects[1].filenames["Content-Disposition"]
|
|
101
|
+
|
|
102
|
+
def __enter__(self):
|
|
103
|
+
return self
|
|
104
|
+
|
|
105
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_basic() -> None:
|
|
110
|
+
"""test basics"""
|
|
111
|
+
sendmail.MIMEMULTIPART = MockMultipart
|
|
112
|
+
sendmail.MIMETEXT = MockText
|
|
113
|
+
sendmail.MIMEIMAGE = MockImage
|
|
114
|
+
sendmail.SMTP = MockSmtp
|
|
115
|
+
sendmail.SMTPSSL = MockSmtp
|
|
116
|
+
settings = {
|
|
117
|
+
"smtp.sender": "from@domain.com",
|
|
118
|
+
"smtp.server": "smtp.com",
|
|
119
|
+
"smtp.port": 1234,
|
|
120
|
+
"smtp.password": "setec astronomy",
|
|
121
|
+
}
|
|
122
|
+
send_email(
|
|
123
|
+
"to@domain.com", "subject", "body", settings, image1=b"\x89PNG\r\n\x1a\n0000"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_unknown_image_type() -> None:
|
|
128
|
+
"""test basics"""
|
|
129
|
+
sendmail.MIMEMULTIPART = MockMultipart
|
|
130
|
+
sendmail.MIMETEXT = MockText
|
|
131
|
+
sendmail.MIMEIMAGE = MockImage
|
|
132
|
+
sendmail.SMTP = MockSmtp
|
|
133
|
+
sendmail.SMTPSSL = MockSmtp
|
|
134
|
+
settings = {
|
|
135
|
+
"smtp.sender": "from@domain.com",
|
|
136
|
+
"smtp.server": "smtp.com",
|
|
137
|
+
"smtp.port": 1234,
|
|
138
|
+
"smtp.password": "setec astronomy",
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
send_email("to@domain.com", "subject", "body", settings, image1=b"bwahaha")
|
|
143
|
+
raise AssertionError("We should have thrown")
|
|
144
|
+
|
|
145
|
+
except AttributeError:
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
test_unknown_image_type()
|
|
151
|
+
test_basic()
|
|
@@ -9,7 +9,8 @@ from itertools import product
|
|
|
9
9
|
|
|
10
10
|
from helpers import setup_settings, ensure, write
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
from devopsdriver import settings # debug access
|
|
13
|
+
from devopsdriver import Settings
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def __setup_files(directory: str, dir1: str, dir2: str) -> None:
|
|
@@ -40,9 +41,9 @@ def __setup_files(directory: str, dir1: str, dir2: str) -> None:
|
|
|
40
41
|
<pref>/test.yaml w
|
|
41
42
|
<pref>/test.json x
|
|
42
43
|
"""
|
|
43
|
-
lin_dir = ensure(
|
|
44
|
-
mac_dir = ensure(
|
|
45
|
-
win_dir = ensure(
|
|
44
|
+
lin_dir = ensure(Settings.PREF_DIR["Linux"])
|
|
45
|
+
mac_dir = ensure(Settings.PREF_DIR["Darwin"])
|
|
46
|
+
win_dir = ensure(Settings.PREF_DIR["Windows"])
|
|
46
47
|
letters = list(ascii_lowercase)
|
|
47
48
|
|
|
48
49
|
for name in ("test", "main"):
|
|
@@ -90,9 +91,7 @@ def test_basic():
|
|
|
90
91
|
}
|
|
91
92
|
settings.ARGV = ["exe", "--beta", "bbcli", "--zeta", "zzcli"]
|
|
92
93
|
opts = (
|
|
93
|
-
|
|
94
|
-
join(base_dir, "main.py"), dir1, dir2, aa=1, bb=2, cc=3
|
|
95
|
-
)
|
|
94
|
+
Settings(join(base_dir, "main.py"), dir1, dir2, aa=1, bb=2, cc=3)
|
|
96
95
|
.cli("bb", "--beta")
|
|
97
96
|
.cli("zz", "--zeta")
|
|
98
97
|
.env("aa", "alpha")
|
|
@@ -204,11 +203,7 @@ def test_cli_env_in_yaml():
|
|
|
204
203
|
"--delta",
|
|
205
204
|
"cli dd",
|
|
206
205
|
]
|
|
207
|
-
opts = (
|
|
208
|
-
settings.Settings(join(base_dir, "main.py"), aa="code aa")
|
|
209
|
-
.cli("cli")
|
|
210
|
-
.env("env")
|
|
211
|
-
)
|
|
206
|
+
opts = Settings(join(base_dir, "main.py"), aa="code aa").cli("cli").env("env")
|
|
212
207
|
assert opts["aa"] == "code aa", opts["aa"]
|
|
213
208
|
assert opts["bb"] == "cli bb", opts["bb"]
|
|
214
209
|
assert opts["dd"] == "cli dd", opts["dd"]
|
|
@@ -237,11 +232,7 @@ def test_environ_values():
|
|
|
237
232
|
"HOME": "sweet home",
|
|
238
233
|
"APPDIR": "app data dir",
|
|
239
234
|
}
|
|
240
|
-
opts = (
|
|
241
|
-
settings.Settings(join(base_dir, "main.py"), aa="code aa")
|
|
242
|
-
.cli("cli")
|
|
243
|
-
.env("env")
|
|
244
|
-
)
|
|
235
|
+
opts = Settings(join(base_dir, "main.py"), aa="code aa").cli("cli").env("env")
|
|
245
236
|
assert opts["output"] == "sweet home/reports", opts["output"]
|
|
246
237
|
assert opts["settings"] == "app data dir/settings.json", opts["settings"]
|
|
247
238
|
assert opts["value"] == "testing ${noenv} for noenv", opts["value"]
|
|
@@ -256,6 +247,15 @@ def test_main():
|
|
|
256
247
|
settings.main()
|
|
257
248
|
|
|
258
249
|
|
|
250
|
+
def test_main_help():
|
|
251
|
+
"""test the main entry point"""
|
|
252
|
+
with TemporaryDirectory() as working_dir:
|
|
253
|
+
setup_settings(shared="test", Linux=join(working_dir, "Linux"))
|
|
254
|
+
settings.ARGV = ["ignore", "--help"]
|
|
255
|
+
write(join(working_dir, "Linux", "test.yml"), test=3)
|
|
256
|
+
settings.main()
|
|
257
|
+
|
|
258
|
+
|
|
259
259
|
def test_secret():
|
|
260
260
|
"""test os secret storage"""
|
|
261
261
|
with TemporaryDirectory() as working_dir:
|
|
@@ -270,9 +270,7 @@ def test_secret():
|
|
|
270
270
|
)
|
|
271
271
|
settings.GET_PASSWORD = lambda s, e: passwords.get(s, {}).get(e, None)
|
|
272
272
|
write(join(base_dir, "main.yml"), password="main")
|
|
273
|
-
opts =
|
|
274
|
-
"password", "system/john"
|
|
275
|
-
)
|
|
273
|
+
opts = Settings(join(base_dir, "main.py")).key("password", "system/john")
|
|
276
274
|
assert opts["password"] == "setec astronomy", opts["password"]
|
|
277
275
|
|
|
278
276
|
|
|
File without changes
|
{devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{devopsdriver-0.1.35/devopsdriver/azure → devopsdriver-0.1.36/devopsdriver/azdo}/workitem/wiql.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|