bugdantic 0.4.3__tar.gz → 0.5.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.
- {bugdantic-0.4.3 → bugdantic-0.5.0}/PKG-INFO +1 -1
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic/bugzilla.py +52 -13
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic.egg-info/PKG-INFO +1 -1
- {bugdantic-0.4.3 → bugdantic-0.5.0}/pyproject.toml +1 -1
- {bugdantic-0.4.3 → bugdantic-0.5.0}/test/test_bugzilla.py +44 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/LICENSE +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/README.md +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic/__init__.py +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic/py.typed +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic/userstory.py +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic.egg-info/SOURCES.txt +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic.egg-info/dependency_links.txt +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic.egg-info/requires.txt +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/bugdantic.egg-info/top_level.txt +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/setup.cfg +0 -0
- {bugdantic-0.4.3 → bugdantic-0.5.0}/test/test_userstory.py +0 -0
|
@@ -455,10 +455,19 @@ def bug_search_model(bug_type: type[BugType]) -> type[BugSearchGeneric[BugType]]
|
|
|
455
455
|
|
|
456
456
|
|
|
457
457
|
def model_field_names(model: type[BaseModel]) -> list[str]:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
458
|
+
field_names = []
|
|
459
|
+
for name, field_obj in model.model_fields.items():
|
|
460
|
+
if field_obj.validation_alias is not None:
|
|
461
|
+
if not isinstance(field_obj.validation_alias, str):
|
|
462
|
+
raise ValueError(
|
|
463
|
+
"Only string values for validation_alias are supported"
|
|
464
|
+
)
|
|
465
|
+
field_names.append(field_obj.validation_alias)
|
|
466
|
+
elif field_obj.alias is not None:
|
|
467
|
+
field_names.append(field_obj.alias)
|
|
468
|
+
else:
|
|
469
|
+
field_names.append(name)
|
|
470
|
+
return field_names
|
|
462
471
|
|
|
463
472
|
|
|
464
473
|
class Bugzilla:
|
|
@@ -555,11 +564,17 @@ class Bugzilla:
|
|
|
555
564
|
bug_id: int,
|
|
556
565
|
bug_type: type[BugType],
|
|
557
566
|
include_fields: Optional[list[str]] = None,
|
|
567
|
+
exclude_fields: Optional[list[str]] = None,
|
|
558
568
|
) -> Optional[BugType]:
|
|
559
569
|
"""Get a single bug specified by id"""
|
|
560
570
|
|
|
561
571
|
data = self.check_error(
|
|
562
|
-
self.request(
|
|
572
|
+
self.request(
|
|
573
|
+
"GET",
|
|
574
|
+
f"bug/{bug_id}",
|
|
575
|
+
include_fields=include_fields,
|
|
576
|
+
exclude_fields=exclude_fields,
|
|
577
|
+
)
|
|
563
578
|
)
|
|
564
579
|
search_result = bug_search_model(bug_type).model_validate(data)
|
|
565
580
|
if search_result.faults:
|
|
@@ -571,18 +586,27 @@ class Bugzilla:
|
|
|
571
586
|
return bugs[0]
|
|
572
587
|
|
|
573
588
|
def bug(
|
|
574
|
-
self,
|
|
589
|
+
self,
|
|
590
|
+
bug_id: int,
|
|
591
|
+
include_fields: Optional[list[str]] = None,
|
|
592
|
+
exclude_fields: Optional[list[str]] = None,
|
|
575
593
|
) -> Optional[Bug]:
|
|
576
|
-
return self._bug(bug_id, Bug, include_fields)
|
|
594
|
+
return self._bug(bug_id, Bug, include_fields, exclude_fields)
|
|
577
595
|
|
|
578
|
-
def bug_as(
|
|
596
|
+
def bug_as(
|
|
597
|
+
self,
|
|
598
|
+
bug_id: int,
|
|
599
|
+
bug_type: type[BugType],
|
|
600
|
+
exclude_fields: Optional[list[str]] = None,
|
|
601
|
+
) -> Optional[BugType]:
|
|
579
602
|
include_fields = model_field_names(bug_type)
|
|
580
|
-
return self._bug(bug_id, bug_type, include_fields)
|
|
603
|
+
return self._bug(bug_id, bug_type, include_fields, exclude_fields)
|
|
581
604
|
|
|
582
605
|
def bugs(
|
|
583
606
|
self,
|
|
584
607
|
bug_ids: Sequence[int],
|
|
585
608
|
include_fields: Optional[list[str]] = None,
|
|
609
|
+
exclude_fields: Optional[list[str]] = None,
|
|
586
610
|
page_size: int = 100,
|
|
587
611
|
) -> list[Bug]:
|
|
588
612
|
"""Get multiple bugs specified by id"""
|
|
@@ -594,6 +618,7 @@ class Bugzilla:
|
|
|
594
618
|
self.search(
|
|
595
619
|
{"id": ",".join(str(id) for id in bug_ids_chunk)},
|
|
596
620
|
include_fields=include_fields,
|
|
621
|
+
exclude_fields=exclude_fields,
|
|
597
622
|
)
|
|
598
623
|
)
|
|
599
624
|
return results
|
|
@@ -602,6 +627,7 @@ class Bugzilla:
|
|
|
602
627
|
self,
|
|
603
628
|
bug_ids: Sequence[int],
|
|
604
629
|
bug_type: type[BugType],
|
|
630
|
+
exclude_fields: Optional[list[str]] = None,
|
|
605
631
|
page_size: int = 100,
|
|
606
632
|
) -> list[BugType]:
|
|
607
633
|
"""Get multiple bugs specified by id"""
|
|
@@ -613,6 +639,7 @@ class Bugzilla:
|
|
|
613
639
|
self.search_as(
|
|
614
640
|
{"id": ",".join(str(id) for id in bug_ids_chunk)},
|
|
615
641
|
bug_type,
|
|
642
|
+
exclude_fields,
|
|
616
643
|
)
|
|
617
644
|
)
|
|
618
645
|
return results
|
|
@@ -641,6 +668,7 @@ class Bugzilla:
|
|
|
641
668
|
bug_type: type[BugType],
|
|
642
669
|
query: QueryParams,
|
|
643
670
|
include_fields: Optional[list[str]] = None,
|
|
671
|
+
exclude_fields: Optional[list[str]] = None,
|
|
644
672
|
page_size: int = 100,
|
|
645
673
|
) -> list[BugType]:
|
|
646
674
|
"""Search for bugs using the bugzilla query API"""
|
|
@@ -656,7 +684,13 @@ class Bugzilla:
|
|
|
656
684
|
results: list[BugType] = []
|
|
657
685
|
while True:
|
|
658
686
|
response = self.check_error(
|
|
659
|
-
self.request(
|
|
687
|
+
self.request(
|
|
688
|
+
"GET",
|
|
689
|
+
"bug",
|
|
690
|
+
params=query,
|
|
691
|
+
include_fields=include_fields,
|
|
692
|
+
exclude_fields=exclude_fields,
|
|
693
|
+
)
|
|
660
694
|
)
|
|
661
695
|
search_result = bug_search_model(bug_type).model_validate(response)
|
|
662
696
|
if search_result.faults:
|
|
@@ -680,15 +714,20 @@ class Bugzilla:
|
|
|
680
714
|
self,
|
|
681
715
|
query: QueryParams,
|
|
682
716
|
include_fields: Optional[list[str]] = None,
|
|
717
|
+
exclude_fields: Optional[list[str]] = None,
|
|
683
718
|
page_size: int = 100,
|
|
684
719
|
) -> list[Bug]:
|
|
685
|
-
return self._search(Bug, query, include_fields, page_size)
|
|
720
|
+
return self._search(Bug, query, include_fields, exclude_fields, page_size)
|
|
686
721
|
|
|
687
722
|
def search_as(
|
|
688
|
-
self,
|
|
723
|
+
self,
|
|
724
|
+
query: QueryParams,
|
|
725
|
+
bug_type: type[BugType],
|
|
726
|
+
exclude_fields: Optional[list[str]] = None,
|
|
727
|
+
page_size: int = 100,
|
|
689
728
|
) -> list[BugType]:
|
|
690
729
|
include_fields = model_field_names(bug_type)
|
|
691
|
-
return self._search(bug_type, query, include_fields, page_size)
|
|
730
|
+
return self._search(bug_type, query, include_fields, exclude_fields, page_size)
|
|
692
731
|
|
|
693
732
|
def update_bugs(
|
|
694
733
|
self, update_params: BugUpdate, bug_id: Optional[int] = None
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
from pydantic import BaseModel, Field
|
|
3
5
|
|
|
@@ -45,6 +47,23 @@ def test_search_include_comments_and_attachments(bugzilla):
|
|
|
45
47
|
assert bug.id == expected_id
|
|
46
48
|
assert isinstance(bug.comments, list)
|
|
47
49
|
assert isinstance(bug.attachments, list)
|
|
50
|
+
for item in bug.attachments:
|
|
51
|
+
assert "data" not in item
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_search_include_attachments_exclude_data(bugzilla):
|
|
55
|
+
bugs = [423488, 1749533]
|
|
56
|
+
result = bugzilla.search(
|
|
57
|
+
{"id": bugs},
|
|
58
|
+
include_fields=["id", "comments", "attachments"],
|
|
59
|
+
exclude_fields=["attachments.data"],
|
|
60
|
+
)
|
|
61
|
+
for expected_id, bug in zip(bugs, sorted(result, key=lambda x: x.id)):
|
|
62
|
+
assert bug.id == expected_id
|
|
63
|
+
assert isinstance(bug.comments, list)
|
|
64
|
+
assert isinstance(bug.attachments, list)
|
|
65
|
+
for item in bug.attachments:
|
|
66
|
+
assert "data" not in item
|
|
48
67
|
|
|
49
68
|
|
|
50
69
|
def test_bug_as(bugzilla):
|
|
@@ -80,3 +99,28 @@ def test_bug_as_alias(bugzilla):
|
|
|
80
99
|
assert isinstance(result, BugData)
|
|
81
100
|
assert result.id == 975444
|
|
82
101
|
assert result.user_story is not None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_bug_as_validation_alias(bugzilla):
|
|
105
|
+
class BugData(BaseModel):
|
|
106
|
+
id: int
|
|
107
|
+
user_story: str = Field(
|
|
108
|
+
validation_alias="cf_user_story", alias="raw_user_story"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
result = bugzilla.bug_as(975444, BugData)
|
|
112
|
+
assert isinstance(result, BugData)
|
|
113
|
+
assert result.id == 975444
|
|
114
|
+
assert result.user_story is not None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_bug_as_exclude(bugzilla):
|
|
118
|
+
class BugData(BaseModel):
|
|
119
|
+
id: int
|
|
120
|
+
attachments: list[dict[str, Any]]
|
|
121
|
+
|
|
122
|
+
result = bugzilla.bug_as(975444, BugData, exclude_fields=["attachments.data"])
|
|
123
|
+
assert isinstance(result, BugData)
|
|
124
|
+
assert result.id == 975444
|
|
125
|
+
assert result.attachments
|
|
126
|
+
assert all("data" not in item for item in result.attachments)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|