pingintel-api 1.4.7__tar.gz → 1.4.9__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.
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/PKG-INFO +1 -1
- pingintel_api-1.4.9/examples/close_submissions.py +129 -0
- pingintel_api-1.4.9/src/pingintel_api/__about__.py +1 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingvision/pingvision_api_client.py +1 -1
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/sov_fixer/sov_fixer_api_client.py +5 -0
- pingintel_api-1.4.7/src/pingintel_api/__about__.py +0 -1
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/.claude/settings.json +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/.claude/settings.local.json +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/.gitignore +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/.pre-commit-config.yaml +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/LICENSE +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/README.md +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/SOV10 2026-02_Acc-STG.txt +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/Untitled-9.json5 +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/assignment_queue.xlsx +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/completed_submissions.xlsx +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/data/demo_email.eml +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/data/parse_sov_testfile.xlsx +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/find-amwins-missing-account-numbers.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-data/enhance_multiple_locations.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-data/enhance_one_location.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-data/pingdata_enhance.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/parse_sov.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/sovfixer_fix_sov.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/sovfixer_list_activity.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/sovfixer_reoutput_sov.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/clear_and_triage_api.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/pingvision_activity.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/pingvision_clear_and_triage.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/send_and_track_submission.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/pingvision_assignment.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/pingvision_declination_flow.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/sovfixer_list_history.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/sovfixer_list_history_ping_None_1_run2.csv +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/sovfixerapi +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/test_reoutput_locations.csv +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/test_sov.xlsx +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/generate_docs.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/justfile +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/output-data-f432c75e-b40e-11f0-9e68-3c58c2f91432-1.json +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/pyproject.toml +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/requirements.txt +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/__init__.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/api_client_base.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/common_types.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/constants.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingdata/pingdata_api_client.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingdata/types.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingdataapi_cmd.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingmaps/pingmaps_api_client.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingmaps/types.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingmapsapi_cmd.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingvision/types.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingvisionapi_cmd.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/sov_fixer/types.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/sovfixerapi_cmd.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/url_signature_factory.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/utils.py +0 -0
- {pingintel_api-1.4.7 → pingintel_api-1.4.9}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingintel-api
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.9
|
|
4
4
|
Summary: Python-based client to Ping Data Intelligence APIs
|
|
5
5
|
Project-URL: Homepage, https://github.com/pingintel/pingintel-api
|
|
6
6
|
Project-URL: Issues, https://github.com/pingintel/pingintel-api/issues
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Set one or more PingVision submissions to a given workflow status.
|
|
3
|
+
|
|
4
|
+
Accepts pingids (e.g. p-ob-amw-agtdgc) or client_refs. Identifiers starting
|
|
5
|
+
with "p-" are treated as pingids; all others are looked up as client_refs.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python close_submissions.py <id1> [id2 ...] --status <name> [options]
|
|
9
|
+
|
|
10
|
+
python close_submissions.py p-ob-amw-abc123 my-client-ref-456 --status Closed
|
|
11
|
+
python close_submissions.py p-ob-amw-abc123 --status Declined --env staging --dry-run
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from pingintel_api import PingVisionAPIClient
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def resolve_pingids(client: PingVisionAPIClient, identifiers: list[str]) -> dict[str, str | None]:
|
|
21
|
+
"""Return {identifier: pingid} for all identifiers. pingid is None if not found."""
|
|
22
|
+
result = {}
|
|
23
|
+
for ident in identifiers:
|
|
24
|
+
if ident.startswith("p-"):
|
|
25
|
+
result[ident] = ident
|
|
26
|
+
else:
|
|
27
|
+
activity = client.list_submission_activity(client_ref=ident, page_size=10)
|
|
28
|
+
submissions = activity.get("results", [])
|
|
29
|
+
if not submissions:
|
|
30
|
+
print(f" WARNING: No submission found for client_ref={ident!r}", file=sys.stderr)
|
|
31
|
+
result[ident] = None
|
|
32
|
+
elif len(submissions) > 1:
|
|
33
|
+
pingids = [s["id"] for s in submissions]
|
|
34
|
+
print(
|
|
35
|
+
f" WARNING: Multiple submissions found for client_ref={ident!r}: {pingids}. Skipping.",
|
|
36
|
+
file=sys.stderr,
|
|
37
|
+
)
|
|
38
|
+
result[ident] = None
|
|
39
|
+
else:
|
|
40
|
+
result[ident] = submissions[0]["id"]
|
|
41
|
+
return result
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def find_status_uuid(client: PingVisionAPIClient, division_uuid: str, status_name: str) -> str:
|
|
45
|
+
statuses = client.list_submission_statuses(division=division_uuid)
|
|
46
|
+
matched = [s for s in statuses if s["name"].lower() == status_name.lower()]
|
|
47
|
+
if not matched:
|
|
48
|
+
available = [s["name"] for s in statuses]
|
|
49
|
+
raise RuntimeError(f"Status {status_name!r} not found. Available: {available}")
|
|
50
|
+
return matched[0]["uuid"]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def find_division_uuid(client: PingVisionAPIClient, team_name: str | None, division: str | None) -> str:
|
|
54
|
+
teams = client.list_teams()
|
|
55
|
+
if not teams:
|
|
56
|
+
raise RuntimeError("No teams found for this API token.")
|
|
57
|
+
if division:
|
|
58
|
+
matched = [
|
|
59
|
+
t for t in teams
|
|
60
|
+
if t["division_uuid"] == division
|
|
61
|
+
or t.get("division_name", "").lower() == division.lower()
|
|
62
|
+
or t.get("division_short_name", "").lower() == division.lower()
|
|
63
|
+
]
|
|
64
|
+
if not matched:
|
|
65
|
+
available = [(t.get("division_short_name") or t["division_name"], t["division_uuid"]) for t in teams]
|
|
66
|
+
raise RuntimeError(f"Division {division!r} not found. Available: {available}")
|
|
67
|
+
return matched[0]["division_uuid"]
|
|
68
|
+
if team_name:
|
|
69
|
+
matched = [t for t in teams if t["team_name"] == team_name]
|
|
70
|
+
if not matched:
|
|
71
|
+
available = [t["team_name"] for t in teams]
|
|
72
|
+
raise RuntimeError(f"Team {team_name!r} not found. Available: {available}")
|
|
73
|
+
return matched[0]["division_uuid"]
|
|
74
|
+
if len(teams) == 1:
|
|
75
|
+
return teams[0]["division_uuid"]
|
|
76
|
+
names = [t["team_name"] for t in teams]
|
|
77
|
+
raise RuntimeError(f"Multiple teams found: {names}. Specify one with --team or --division.")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def main():
|
|
81
|
+
parser = argparse.ArgumentParser(description="Set PingVision submission workflow status.")
|
|
82
|
+
parser.add_argument("identifiers", nargs="+", help="pingids or client_refs to update")
|
|
83
|
+
parser.add_argument("--status", required=True, help="Target workflow status name (e.g. Closed, Declined)")
|
|
84
|
+
parser.add_argument("--env", default="prod", help="API environment (prod, staging, local). Default: prod")
|
|
85
|
+
parser.add_argument("--api-url", help="Override API URL (e.g. http://localhost:8002)")
|
|
86
|
+
parser.add_argument("--team", help="Team name for status lookup (required if multiple teams)")
|
|
87
|
+
parser.add_argument("--division", help="Division UUID (alternative to --team)")
|
|
88
|
+
parser.add_argument("--dry-run", action="store_true", help="Print what would happen without making changes")
|
|
89
|
+
args = parser.parse_args()
|
|
90
|
+
|
|
91
|
+
kwargs = {}
|
|
92
|
+
if args.api_url:
|
|
93
|
+
kwargs["api_url"] = args.api_url
|
|
94
|
+
else:
|
|
95
|
+
kwargs["environment"] = args.env
|
|
96
|
+
|
|
97
|
+
client = PingVisionAPIClient(**kwargs)
|
|
98
|
+
|
|
99
|
+
division_uuid = find_division_uuid(client, args.team, args.division)
|
|
100
|
+
status_uuid = find_status_uuid(client, division_uuid, args.status)
|
|
101
|
+
print(f"Status {args.status!r} UUID: {status_uuid}")
|
|
102
|
+
|
|
103
|
+
id_map = resolve_pingids(client, args.identifiers)
|
|
104
|
+
|
|
105
|
+
success, skipped, failed = 0, 0, 0
|
|
106
|
+
for ident, pingid in id_map.items():
|
|
107
|
+
if pingid is None:
|
|
108
|
+
skipped += 1
|
|
109
|
+
continue
|
|
110
|
+
label = pingid if ident == pingid else f"{pingid} (client_ref={ident!r})"
|
|
111
|
+
if args.dry_run:
|
|
112
|
+
print(f" DRY RUN: would set {label} -> {args.status!r}")
|
|
113
|
+
success += 1
|
|
114
|
+
continue
|
|
115
|
+
try:
|
|
116
|
+
client.change_status(pingid=pingid, workflow_status_id=status_uuid)
|
|
117
|
+
print(f" Updated {label} -> {args.status!r}")
|
|
118
|
+
success += 1
|
|
119
|
+
except Exception as e:
|
|
120
|
+
print(f" ERROR updating {label}: {e}", file=sys.stderr)
|
|
121
|
+
failed += 1
|
|
122
|
+
|
|
123
|
+
print(f"\nDone. {success} updated, {skipped} skipped, {failed} failed.")
|
|
124
|
+
if failed:
|
|
125
|
+
sys.exit(1)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.4.9"
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingvision/pingvision_api_client.py
RENAMED
|
@@ -182,7 +182,7 @@ class PingVisionAPIClient(APIClientBase):
|
|
|
182
182
|
else:
|
|
183
183
|
url = self.api_url + document_url
|
|
184
184
|
|
|
185
|
-
assert url.startswith(self.api_url), f"document_url should start with {self.api_url} or / but got {url}"
|
|
185
|
+
# assert url.startswith(self.api_url), f"document_url should start with {self.api_url} or / but got {url}"
|
|
186
186
|
|
|
187
187
|
response = self.get(url)
|
|
188
188
|
raise_for_status(response)
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/sov_fixer/sov_fixer_api_client.py
RENAMED
|
@@ -624,6 +624,7 @@ class SOVFixerAPIClient(APIClientBase):
|
|
|
624
624
|
revision: int = -1,
|
|
625
625
|
overwrite_existing: bool = False,
|
|
626
626
|
delegate_to_team: UUID | str | int | None = None,
|
|
627
|
+
**kwargs,
|
|
627
628
|
):
|
|
628
629
|
url = self.api_url + f"/api/v1/sov/{sovid_or_sud}/get_or_create_output"
|
|
629
630
|
data = {}
|
|
@@ -635,6 +636,8 @@ class SOVFixerAPIClient(APIClientBase):
|
|
|
635
636
|
data["overwrite_existing"] = overwrite_existing
|
|
636
637
|
if delegate_to_team is not None:
|
|
637
638
|
data["delegate_to_team"] = delegate_to_team
|
|
639
|
+
if kwargs:
|
|
640
|
+
data.update(kwargs)
|
|
638
641
|
|
|
639
642
|
response = self.post(url, data=data)
|
|
640
643
|
raise_for_status(response)
|
|
@@ -654,6 +657,7 @@ class SOVFixerAPIClient(APIClientBase):
|
|
|
654
657
|
overwrite_existing=False,
|
|
655
658
|
timeout: timedelta | None = timedelta(minutes=5),
|
|
656
659
|
delegate_to_team: UUID | str | int | None = None,
|
|
660
|
+
get_or_create_output_async_start_kwargs=None,
|
|
657
661
|
) -> t.OutputData:
|
|
658
662
|
"""Synchronously get or create an output from a SOV Fixer request. If it exists, it will return immediately.
|
|
659
663
|
If it does not exist, it will start the generation process and poll for completion, then return it."""
|
|
@@ -665,6 +669,7 @@ class SOVFixerAPIClient(APIClientBase):
|
|
|
665
669
|
revision,
|
|
666
670
|
overwrite_existing,
|
|
667
671
|
delegate_to_team,
|
|
672
|
+
**(get_or_create_output_async_start_kwargs or {}),
|
|
668
673
|
)
|
|
669
674
|
|
|
670
675
|
request_status = start_response["request"]["status"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.4.7"
|
|
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
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-data/enhance_multiple_locations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/sovfixer_list_activity.py
RENAMED
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-extraction/sovfixer_reoutput_sov.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/pingvision_clear_and_triage.py
RENAMED
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/ping-vision/send_and_track_submission.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/examples/sovfixer_list_history_ping_None_1_run2.csv
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/output-data-f432c75e-b40e-11f0-9e68-3c58c2f91432-1.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingdata/pingdata_api_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingintel_api-1.4.7 → pingintel_api-1.4.9}/src/pingintel_api/pingmaps/pingmaps_api_client.py
RENAMED
|
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
|