devopsdriver 0.1.43__tar.gz → 0.1.45__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.
Files changed (48) hide show
  1. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/PKG-INFO +5 -5
  2. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/README.md +1 -1
  3. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/__init__.py +1 -1
  4. devopsdriver-0.1.45/devopsdriver/azdo/builds/build.py +74 -0
  5. devopsdriver-0.1.45/devopsdriver/azdo/builds/client.py +59 -0
  6. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/clients.py +17 -4
  7. devopsdriver-0.1.45/devopsdriver/azdo/pipeline/__init__.py +12 -0
  8. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/pipeline/run.py +1 -1
  9. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/workitem/client.py +3 -2
  10. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/dataobject.py +9 -0
  11. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/PKG-INFO +5 -5
  12. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/SOURCES.txt +5 -0
  13. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/requires.txt +2 -2
  14. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/pyproject.toml +3 -3
  15. devopsdriver-0.1.45/tests/test_azure_build.py +99 -0
  16. devopsdriver-0.1.45/tests/test_azure_build_client.py +76 -0
  17. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_clients.py +32 -7
  18. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_pipeline_run.py +1 -1
  19. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_workitem_client.py +1 -1
  20. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/LICENSE +0 -0
  21. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/__init__.py +0 -0
  22. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/azureobject.py +0 -0
  23. {devopsdriver-0.1.43/devopsdriver/azdo/pipeline → devopsdriver-0.1.45/devopsdriver/azdo/builds}/__init__.py +0 -0
  24. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/pipeline/client.py +0 -0
  25. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/pipeline/log.py +0 -0
  26. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/pipeline/pipeline.py +0 -0
  27. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/timestamp.py +0 -0
  28. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/workitem/__init__.py +0 -0
  29. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/azdo/workitem/wiql.py +0 -0
  30. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/manage_settings.py +0 -0
  31. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/sendmail.py +0 -0
  32. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/settings.py +0 -0
  33. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/template.py +0 -0
  34. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver/templates/manage_settings.txt.mako +0 -0
  35. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/dependency_links.txt +0 -0
  36. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/entry_points.txt +0 -0
  37. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/devopsdriver.egg-info/top_level.txt +0 -0
  38. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/setup.cfg +0 -0
  39. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_azureobject.py +0 -0
  40. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_pipeline.py +0 -0
  41. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_pipeline_client.py +0 -0
  42. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_timestamp.py +0 -0
  43. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_azure_workitem_wiql.py +0 -0
  44. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_dataobject.py +0 -0
  45. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_manage_settings.py +0 -0
  46. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_sendmail.py +0 -0
  47. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_settings.py +0 -0
  48. {devopsdriver-0.1.43 → devopsdriver-0.1.45}/tests/test_template.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devopsdriver
3
- Version: 0.1.43
3
+ Version: 0.1.45
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.
@@ -40,7 +40,7 @@ Classifier: Intended Audience :: Developers
40
40
  Classifier: Programming Language :: Python
41
41
  Classifier: Programming Language :: Python :: 3
42
42
  Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
43
- Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Programming Language :: Python :: 3.10
44
44
  Classifier: Topic :: Utilities
45
45
  Classifier: Topic :: Software Development
46
46
  Requires-Python: >=3.10
@@ -48,9 +48,9 @@ Description-Content-Type: text/markdown
48
48
  License-File: LICENSE
49
49
  Requires-Dist: PyYAML==6.0.1
50
50
  Requires-Dist: keyring==25.1.0
51
- Requires-Dist: setuptools==69.2.0
51
+ Requires-Dist: setuptools==69.5.1
52
52
  Requires-Dist: azure-devops==7.1.0b4
53
- Requires-Dist: Mako==1.3.2
53
+ Requires-Dist: Mako==1.3.3
54
54
  Provides-Extra: dev
55
55
  Requires-Dist: black>=24.3.0; extra == "dev"
56
56
  Requires-Dist: pylint>=3.1.0; extra == "dev"
@@ -60,7 +60,7 @@ Requires-Dist: coverage>=7.4.4; extra == "test"
60
60
  Provides-Extra: doc
61
61
 
62
62
  ![status sheild](https://img.shields.io/static/v1?label=status&message=beta&color=blue&style=plastic)
63
- [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.43&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.43/)
63
+ [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.45&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.45/)
64
64
  [![GitHub](https://img.shields.io/github/license/marcpage/devops-driver?style=plastic)](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
65
65
  [![GitHub contributors](https://img.shields.io/github/contributors/marcpage/devops-driver?style=flat)](https://github.com/marcpage/devops-driver/graphs/contributors)
66
66
  [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com)
@@ -1,5 +1,5 @@
1
1
  ![status sheild](https://img.shields.io/static/v1?label=status&message=beta&color=blue&style=plastic)
2
- [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.43&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.43/)
2
+ [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.45&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.45/)
3
3
  [![GitHub](https://img.shields.io/github/license/marcpage/devops-driver?style=plastic)](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
4
4
  [![GitHub contributors](https://img.shields.io/github/contributors/marcpage/devops-driver?style=flat)](https://github.com/marcpage/devops-driver/graphs/contributors)
5
5
  [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com)
@@ -6,6 +6,6 @@ from .template import Template
6
6
  from .azdo.clients import Azure
7
7
 
8
8
 
9
- __version__ = "0.1.43"
9
+ __version__ = "0.1.45"
10
10
  __author__ = "Marc Page"
11
11
  __credits__ = ""
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """ Azure Build """
4
+
5
+ from azure.devops.v7_1.build.models import Build as AzureBuild
6
+ from azure.devops.v7_1.build import BuildClient
7
+ from azure.devops.v7_1.build.models import TimelineRecord
8
+
9
+ from devopsdriver.azdo import AzureObject
10
+
11
+
12
+ class Build(AzureObject): # pylint: disable=too-few-public-methods
13
+ """Azure Build"""
14
+
15
+ def __init__(self, client: BuildClient, build: AzureBuild):
16
+ self.client = client
17
+ self.build = build
18
+ super().__init__(build)
19
+
20
+ class Step(AzureObject): # pylint: disable=too-few-public-methods
21
+ """Azure Build Step (job, task, step)"""
22
+
23
+ def __init__(self, entry: TimelineRecord):
24
+ self.children = []
25
+ self.log_contents: str = None
26
+ super().__init__(entry)
27
+
28
+ def all_logs(self) -> list[str]:
29
+ """Get a list of all logs in chronological order
30
+
31
+ Returns:
32
+ list[str]: List of all the logs
33
+ """
34
+ logs = [] if self.log_contents is None else [self.log_contents]
35
+
36
+ for child in self.children:
37
+ logs.extend(child.all_logs())
38
+
39
+ return logs
40
+
41
+ def __add_steps_and_logs(self, entry: Step, to_process: list[Step]) -> Step:
42
+ project = self.build.project.name
43
+ build_id = self.build.id
44
+
45
+ if entry.log:
46
+ entry.log_contents = "\n".join(
47
+ self.client.get_build_log_lines(project, build_id, entry.log.id)
48
+ )
49
+
50
+ entry.children = [e for e in to_process if e.parent_id == entry.id]
51
+
52
+ for child in entry.children:
53
+ to_process.remove(child)
54
+ self.__add_steps_and_logs(child, to_process)
55
+
56
+ return entry
57
+
58
+ def get_logs(self) -> Step:
59
+ """Gets the logs in a hierarchical structure
60
+
61
+ Returns:
62
+ Step: The root element of the log hierarchy
63
+ """
64
+ project = self.build.project.name
65
+ build_id = self.build.id
66
+ steps = [
67
+ Build.Step(r)
68
+ for r in self.client.get_build_timeline(project, build_id).records
69
+ ]
70
+ root = [s for s in steps if not s.parent_id]
71
+ assert len(root) == 1, root
72
+ root = root[0]
73
+ steps.remove(root)
74
+ return self.__add_steps_and_logs(root, steps)
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ """ Azure Build Client """
5
+
6
+
7
+ from datetime import datetime
8
+ from azure.devops.v7_1.build import BuildClient
9
+
10
+ from .build import Build
11
+
12
+
13
+ class Client: # pylint: disable=too-few-public-methods
14
+ """The Build client"""
15
+
16
+ def __init__(self, client: BuildClient):
17
+ self.client = client
18
+
19
+ def list( # pylint: disable=too-many-arguments
20
+ self,
21
+ project: str,
22
+ pipelines: list[int] = None,
23
+ start: datetime = None,
24
+ end: datetime = None,
25
+ status: str = None,
26
+ result: str = None,
27
+ properties: list[str] = None,
28
+ branch: str = None,
29
+ ) -> list[Build]:
30
+ """Get the list of builds
31
+
32
+ Args:
33
+ project (str): The name of the project
34
+ pipelines (list[int], optional): List of pipeline ids. Defaults to None.
35
+ start (datetime, optional): Earliest time. Defaults to None.
36
+ end (datetime, optional): Latest time. Defaults to None.
37
+ status (str, optional): The status to get. Defaults to None.
38
+ result (str, optional): The result to get. Defaults to None.
39
+ properties (list[str], optional): List or properties to return. Defaults to None.
40
+ branch (str, optional): The branch to search. Defaults to None.
41
+
42
+ Returns:
43
+ list[Build]: List of all the builds that match the given criteria
44
+ """
45
+ continuation = None
46
+ return [
47
+ Build(self.client, b)
48
+ for b in self.client.get_builds(
49
+ project,
50
+ continuation_token=continuation,
51
+ definitions=pipelines,
52
+ min_time=start,
53
+ max_time=end,
54
+ status_filter=status,
55
+ result_filter=result,
56
+ properties=properties,
57
+ branch_name=branch,
58
+ )
59
+ ]
@@ -14,6 +14,7 @@ from msrest.authentication import BasicAuthentication as MSBasicAuthentication
14
14
  from devopsdriver.settings import Settings
15
15
  from devopsdriver.azdo.workitem.client import Client as WIClient
16
16
  from devopsdriver.azdo.pipeline.client import Client as PLClient
17
+ from devopsdriver.azdo.builds.client import Client as BClient
17
18
 
18
19
 
19
20
  # for testing
@@ -21,16 +22,16 @@ CONNECTION = AzureConnection
21
22
  AUTHENTICATION = MSBasicAuthentication
22
23
 
23
24
 
24
- class Azure: # pylint: disable=too-few-public-methods
25
+ class Azure: # pylint: disable=too-few-public-methods,too-many-instance-attributes
25
26
  """A connection to Azure clients"""
26
27
 
27
- SUPPORTED_CLIENTS = {"workitem", "pipeline"}
28
+ class _Client:
29
+ def __init__(self, client):
30
+ self.client = client
28
31
 
29
32
  def __init__(
30
33
  self, settings: Settings = None, token: str = None, url: str = None, **clients
31
34
  ):
32
- unsupported_clients = set(clients) - Azure.SUPPORTED_CLIENTS
33
- assert not unsupported_clients, f"{unsupported_clients} not supported"
34
35
  settings = (
35
36
  Settings(__file__).key("secrets")
36
37
  if settings is None and token is None and url is None
@@ -47,9 +48,21 @@ class Azure: # pylint: disable=too-few-public-methods
47
48
  client_calls = {
48
49
  "workitem": self.connection.clients_v7_1.get_work_item_tracking_client,
49
50
  "pipeline": self.connection.clients_v7_1.get_pipelines_client,
51
+ "task": self.connection.clients_v7_1.get_task_agent_client,
52
+ "git": self.connection.clients_v7_1.get_git_client,
53
+ "core": self.connection.clients_v7_1.get_core_client,
54
+ "build": self.connection.clients_v7_1.get_build_client,
55
+ "identity": self.connection.clients_v7_1.get_identity_client,
50
56
  }
57
+ unsupported_clients = set(clients) - set(client_calls)
58
+ assert not unsupported_clients, f"{unsupported_clients} not supported"
51
59
  self.workitem = WIClient(Azure.__client("workitem", clients, client_calls))
52
60
  self.pipeline = PLClient(Azure.__client("pipeline", clients, client_calls))
61
+ self.core = Azure._Client(Azure.__client("core", clients, client_calls))
62
+ self.task = Azure._Client(Azure.__client("task", clients, client_calls))
63
+ self.git = Azure._Client(Azure.__client("git", clients, client_calls))
64
+ self.build = BClient(Azure.__client("build", clients, client_calls))
65
+ self.identity = Azure._Client(Azure.__client("identity", clients, client_calls))
53
66
 
54
67
  @staticmethod
55
68
  def __client(name: str, clients: dict, calls: dict) -> any:
@@ -0,0 +1,12 @@
1
+ # pylint: disable=cyclic-import
2
+
3
+ # devopsdriver.azdo
4
+ # -> devopsdriver.azdo.clients
5
+ # -> devopsdriver.azdo.pipeline.client
6
+ # -> devopsdriver.azdo.pipeline.pipeline
7
+
8
+ # devopsdriver.azdo
9
+ # -> devopsdriver.azdo.clients
10
+ # -> devopsdriver.azdo.pipeline.client
11
+ # -> devopsdriver.azdo.pipeline.pipeline
12
+ # -> devopsdriver.azdo.pipeline.run
@@ -35,7 +35,7 @@ class Run(AzureObject): # pylint: disable=too-few-public-methods
35
35
  self.pipeline = pipeline
36
36
  super().__init__(run)
37
37
 
38
- def logs(self):
38
+ def get_logs(self):
39
39
  """Get Logs for the run"""
40
40
  return [
41
41
  Log(l)
@@ -43,7 +43,7 @@ class Client:
43
43
  top=top,
44
44
  )
45
45
 
46
- def history( # pylint: disable=too-many-arguments
46
+ def get_history( # pylint: disable=too-many-arguments
47
47
  self,
48
48
  wi_id: int,
49
49
  project: str = None,
@@ -86,5 +86,6 @@ class Client:
86
86
  list[list[WorkItem]]: List of work items, each is a history of work items
87
87
  """
88
88
  return [
89
- [AzureObject(e) for e in self.history(i)] for i in self.find_ids(wiql, top)
89
+ [AzureObject(e) for e in self.get_history(i)]
90
+ for i in self.find_ids(wiql, top)
90
91
  ]
@@ -3,6 +3,9 @@
3
3
  """ Data Objects """
4
4
 
5
5
 
6
+ from json import dumps
7
+
8
+
6
9
  class DataObject: # pylint: disable=too-few-public-methods
7
10
  """dict like object with fuzzy field matching"""
8
11
 
@@ -46,6 +49,12 @@ class DataObject: # pylint: disable=too-few-public-methods
46
49
  def __getattr__(self, name: str) -> any:
47
50
  return self._get_field(name, self.data)
48
51
 
52
+ def __str__(self) -> str:
53
+ return dumps(self.data, indent=2)
54
+
55
+ def __repr__(self) -> str:
56
+ return dumps(self.data, indent=2)
57
+
49
58
  class _Dict(dict):
50
59
  def __init__(self, dataobject, data: dict):
51
60
  self.dataobject = dataobject
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devopsdriver
3
- Version: 0.1.43
3
+ Version: 0.1.45
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.
@@ -40,7 +40,7 @@ Classifier: Intended Audience :: Developers
40
40
  Classifier: Programming Language :: Python
41
41
  Classifier: Programming Language :: Python :: 3
42
42
  Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
43
- Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Programming Language :: Python :: 3.10
44
44
  Classifier: Topic :: Utilities
45
45
  Classifier: Topic :: Software Development
46
46
  Requires-Python: >=3.10
@@ -48,9 +48,9 @@ Description-Content-Type: text/markdown
48
48
  License-File: LICENSE
49
49
  Requires-Dist: PyYAML==6.0.1
50
50
  Requires-Dist: keyring==25.1.0
51
- Requires-Dist: setuptools==69.2.0
51
+ Requires-Dist: setuptools==69.5.1
52
52
  Requires-Dist: azure-devops==7.1.0b4
53
- Requires-Dist: Mako==1.3.2
53
+ Requires-Dist: Mako==1.3.3
54
54
  Provides-Extra: dev
55
55
  Requires-Dist: black>=24.3.0; extra == "dev"
56
56
  Requires-Dist: pylint>=3.1.0; extra == "dev"
@@ -60,7 +60,7 @@ Requires-Dist: coverage>=7.4.4; extra == "test"
60
60
  Provides-Extra: doc
61
61
 
62
62
  ![status sheild](https://img.shields.io/static/v1?label=status&message=beta&color=blue&style=plastic)
63
- [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.43&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.43/)
63
+ [![status sheild](https://img.shields.io/static/v1?label=released&message=v0.1.45&color=active&style=plastic)](https://pypi.org/project/devopsdriver/0.1.45/)
64
64
  [![GitHub](https://img.shields.io/github/license/marcpage/devops-driver?style=plastic)](https://github.com/marcpage/devops-driver?tab=Unlicense-1-ov-file#readme)
65
65
  [![GitHub contributors](https://img.shields.io/github/contributors/marcpage/devops-driver?style=flat)](https://github.com/marcpage/devops-driver/graphs/contributors)
66
66
  [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com)
@@ -17,6 +17,9 @@ devopsdriver/azdo/__init__.py
17
17
  devopsdriver/azdo/azureobject.py
18
18
  devopsdriver/azdo/clients.py
19
19
  devopsdriver/azdo/timestamp.py
20
+ devopsdriver/azdo/builds/__init__.py
21
+ devopsdriver/azdo/builds/build.py
22
+ devopsdriver/azdo/builds/client.py
20
23
  devopsdriver/azdo/pipeline/__init__.py
21
24
  devopsdriver/azdo/pipeline/client.py
22
25
  devopsdriver/azdo/pipeline/log.py
@@ -27,6 +30,8 @@ devopsdriver/azdo/workitem/client.py
27
30
  devopsdriver/azdo/workitem/wiql.py
28
31
  devopsdriver/templates/manage_settings.txt.mako
29
32
  tests/test_azure_azureobject.py
33
+ tests/test_azure_build.py
34
+ tests/test_azure_build_client.py
30
35
  tests/test_azure_clients.py
31
36
  tests/test_azure_pipeline.py
32
37
  tests/test_azure_pipeline_client.py
@@ -1,8 +1,8 @@
1
1
  PyYAML==6.0.1
2
2
  keyring==25.1.0
3
- setuptools==69.2.0
3
+ setuptools==69.5.1
4
4
  azure-devops==7.1.0b4
5
- Mako==1.3.2
5
+ Mako==1.3.3
6
6
 
7
7
  [dev]
8
8
  black>=24.3.0
@@ -8,9 +8,9 @@ requires-python = ">= 3.10"
8
8
  dependencies = [
9
9
  "PyYAML==6.0.1",
10
10
  "keyring==25.1.0",
11
- "setuptools==69.2.0", # neded for azure-devops to use 7.1 API
11
+ "setuptools==69.5.1", # neded for azure-devops to use 7.1 API
12
12
  "azure-devops==7.1.0b4",
13
- "Mako==1.3.2",
13
+ "Mako==1.3.3",
14
14
  ]
15
15
  keywords = ["azure", "devops", "jira", "confluence", "email", "pipelines", "tools"]
16
16
  classifiers=[
@@ -20,7 +20,7 @@ classifiers=[
20
20
  "Programming Language :: Python",
21
21
  "Programming Language :: Python :: 3",
22
22
  "License :: OSI Approved :: The Unlicense (Unlicense)",
23
- "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.10",
24
24
  "Topic :: Utilities",
25
25
  "Topic :: Software Development",
26
26
  ]
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """ Test build object """
4
+
5
+ from types import SimpleNamespace
6
+
7
+ from devopsdriver.azdo.builds.build import Build
8
+ from devopsdriver.azdo.azureobject import AzureObject
9
+
10
+
11
+ class MockTimeline: # pylint: disable=too-few-public-methods
12
+ """mock timeline"""
13
+
14
+ def __init__(self, d: dict):
15
+ self.d = d
16
+
17
+ def as_dict(self) -> dict:
18
+ """mock as_dict"""
19
+ return self.d
20
+
21
+
22
+ class MockClient:
23
+ """mock build client"""
24
+
25
+ def get_build_log_lines(self, project, build_id, log_id) -> list[str]:
26
+ """mock get_build_log_lines"""
27
+ return [f"project={project}", f"build={build_id}", f"log={log_id}"]
28
+
29
+ def get_build_timeline(self, project, build_id):
30
+ """mock get_build_timeline"""
31
+ return SimpleNamespace(
32
+ records=[
33
+ MockTimeline(
34
+ {
35
+ "parent_id": None,
36
+ "id": "5",
37
+ "project": project,
38
+ "build_id": build_id,
39
+ "log": {"id": 9},
40
+ }
41
+ ),
42
+ MockTimeline(
43
+ {
44
+ "parent_id": "5",
45
+ "id": "6",
46
+ "project": project,
47
+ "build_id": build_id,
48
+ "log": {"id": 6},
49
+ }
50
+ ),
51
+ ]
52
+ )
53
+
54
+
55
+ class MockBuild(AzureObject): # pylint: disable=too-few-public-methods
56
+ """mock build client"""
57
+
58
+ def __init__(self, d: dict):
59
+ self.d = d
60
+ super().__init__(self)
61
+
62
+ def as_dict(self) -> dict:
63
+ """mock as_dict"""
64
+ return self.d
65
+
66
+
67
+ def test_basic() -> None:
68
+ """test basic functionailty"""
69
+ build = Build(MockClient(), MockBuild({"project": {"name": "project"}, "id": 12}))
70
+ logs = build.get_logs().all_logs()
71
+ assert len(logs) == 2, logs
72
+
73
+
74
+ def test_azure_object() -> None:
75
+ """test string conversions for data objects"""
76
+ build = MockBuild({"project": {"name": "project"}, "id": 12})
77
+ assert (
78
+ str(build)
79
+ == """{
80
+ "project": {
81
+ "name": "project"
82
+ },
83
+ "id": 12
84
+ }"""
85
+ ), str(build)
86
+ assert (
87
+ repr(build)
88
+ == """{
89
+ "project": {
90
+ "name": "project"
91
+ },
92
+ "id": 12
93
+ }"""
94
+ ), repr(build)
95
+
96
+
97
+ if __name__ == "__main__":
98
+ test_basic()
99
+ test_azure_object()
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """ Test azure build client """
4
+
5
+ from datetime import datetime
6
+
7
+ from devopsdriver.azdo.builds.client import Client
8
+
9
+
10
+ class MockObject:
11
+ """mock object"""
12
+
13
+ def __init__(self, d: dict):
14
+ self.d = d
15
+
16
+ def as_dict(self) -> dict:
17
+ """mock as_dict
18
+
19
+ Returns:
20
+ dict: the dict
21
+ """
22
+ return self.d
23
+
24
+
25
+ class MockClient:
26
+ """mock build client"""
27
+
28
+ def get_builds(
29
+ self,
30
+ project,
31
+ definitions,
32
+ min_time,
33
+ max_time,
34
+ status_filter,
35
+ result_filter,
36
+ properties,
37
+ branch_name,
38
+ continuation_token=None,
39
+ ):
40
+ """mock get_builds"""
41
+ return [
42
+ MockObject(
43
+ {
44
+ "project": project,
45
+ "pipelines": definitions,
46
+ "start": min_time,
47
+ "end": max_time,
48
+ "status": status_filter,
49
+ "result": result_filter,
50
+ "fields": properties,
51
+ "branch": branch_name,
52
+ "token": continuation_token,
53
+ }
54
+ )
55
+ ]
56
+
57
+
58
+ def test_basic() -> None:
59
+ """Test basic functionality"""
60
+ client = Client(MockClient())
61
+ results = client.list(
62
+ "project",
63
+ [1, 2, 3],
64
+ datetime.now(),
65
+ datetime.now(),
66
+ "completed",
67
+ "success",
68
+ ["id"],
69
+ "main",
70
+ )
71
+ assert len(results) == 1, results
72
+ assert results[0].project == "project"
73
+
74
+
75
+ if __name__ == "__main__":
76
+ test_basic()
@@ -24,13 +24,23 @@ class MockConnection: # pylint: disable=too-few-public-methods
24
24
  class Clients71: # pylint: disable=too-few-public-methods
25
25
  """Fakes a 7.1 clients factory"""
26
26
 
27
- def get_work_item_tracking_client(self) -> str:
28
- """fakes getting work item client"""
29
- return "work_item_tracking_client"
27
+ SUPPORTED = {
28
+ "get_work_item_tracking_client",
29
+ "get_pipelines_client",
30
+ "get_task_agent_client",
31
+ "get_git_client",
32
+ "get_core_client",
33
+ "get_build_client",
34
+ "get_identity_client",
35
+ }
30
36
 
31
- def get_pipelines_client(self) -> str:
32
- """mocks getting pipeline client"""
33
- return "get_pipelines_client"
37
+ def __getattr__(self, name: str) -> str:
38
+ assert name in Clients71.SUPPORTED, name
39
+
40
+ def function():
41
+ return name.replace("get_", "")
42
+
43
+ return function
34
44
 
35
45
  self.clients_v7_1 = Clients71()
36
46
 
@@ -124,7 +134,9 @@ def test_load_settings() -> None:
124
134
  ), azure.connection.base_url
125
135
  assert azure.connection.creds.token == "token", azure.connection.creds.token
126
136
  assert azure.connection.creds.empty == "", azure.connection.creds.empty
127
- assert azure.workitem.client == "work_item_tracking_client"
137
+ assert (
138
+ azure.workitem.client == "work_item_tracking_client"
139
+ ), azure.workitem.client
128
140
 
129
141
 
130
142
  def test_not_all_clients() -> None:
@@ -140,7 +152,20 @@ def test_not_all_clients() -> None:
140
152
  assert azure.workitem.client is None
141
153
 
142
154
 
155
+ def test_unsupported_client() -> None:
156
+ """test the basic calling"""
157
+ clients.CONNECTION = MockConnection
158
+ clients.AUTHENTICATION = lambda a, b: SimpleNamespace(empty=a, token=b)
159
+ try:
160
+ _ = Azure(None, "token", "https://url.com/project", google=True)
161
+ raise KeyError("google should not have worked")
162
+
163
+ except AssertionError as error:
164
+ assert "google" in str(error), error
165
+
166
+
143
167
  if __name__ == "__main__":
168
+ test_unsupported_client()
144
169
  test_not_all_clients()
145
170
  test_load_settings()
146
171
  test_mixed_settings()
@@ -60,7 +60,7 @@ def test_basic() -> None:
60
60
  """test basic run and log"""
61
61
  log.GET_URL = lambda x, timeout: x
62
62
  run = Run(MockPipelineClient(), "project", MockPipeline(5), MockAzureRun(83))
63
- logs = run.logs()
63
+ logs = run.get_logs()
64
64
  assert len(logs) == 2, logs
65
65
 
66
66
 
@@ -44,7 +44,7 @@ def test_basic() -> None:
44
44
  def test_history() -> None:
45
45
  """test history"""
46
46
  client = Client(MockClient())
47
- history = client.history(2)
47
+ history = client.get_history(2)
48
48
  assert not history
49
49
 
50
50
 
File without changes
File without changes