sfq 0.0.29__tar.gz → 0.0.30__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sfq
3
- Version: 0.0.29
3
+ Version: 0.0.30
4
4
  Summary: Python wrapper for the Salesforce's Query API.
5
5
  Author-email: David Moruzzi <sfq.pypi@dmoruzi.com>
6
6
  Keywords: salesforce,salesforce query
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sfq"
3
- version = "0.0.29"
3
+ version = "0.0.30"
4
4
  description = "Python wrapper for the Salesforce's Query API."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "David Moruzzi", email = "sfq.pypi@dmoruzi.com" }]
@@ -99,7 +99,7 @@ class SFAuth:
99
99
  access_token: Optional[str] = None,
100
100
  token_expiration_time: Optional[float] = None,
101
101
  token_lifetime: int = 15 * 60,
102
- user_agent: str = "sfq/0.0.29",
102
+ user_agent: str = "sfq/0.0.30",
103
103
  sforce_client: str = "_auto",
104
104
  proxy: str = "_auto",
105
105
  ) -> None:
@@ -1099,6 +1099,7 @@ class SFAuth:
1099
1099
  insert_list: List[Dict[str, Any]],
1100
1100
  batch_size: int = 200,
1101
1101
  max_workers: int = None,
1102
+ api_type: Literal["enterprise", "tooling", "metadata"] = "enterprise",
1102
1103
  ) -> Optional[Dict[str, Any]]:
1103
1104
  """
1104
1105
  Execute the Insert API to insert multiple records via SOAP calls.
@@ -1110,7 +1111,19 @@ class SFAuth:
1110
1111
  :return: JSON response from the insert request or None on failure.
1111
1112
  """
1112
1113
 
1113
- endpoint = f"/services/Soap/c/{self.api_version}"
1114
+ endpoint = "/services/Soap/"
1115
+ if api_type == "enterprise":
1116
+ endpoint += f"c/{self.api_version}"
1117
+ elif api_type == "tooling":
1118
+ endpoint += f"T/{self.api_version}"
1119
+ elif api_type == "metadata":
1120
+ endpoint += f"m/{self.api_version}"
1121
+ else:
1122
+ logger.error(
1123
+ "Invalid API type: %s. Must be one of: 'enterprise', 'tooling', 'metadata'.",
1124
+ api_type,
1125
+ )
1126
+ return None
1114
1127
 
1115
1128
  if isinstance(insert_list, dict):
1116
1129
  insert_list = [insert_list]
@@ -1165,3 +1178,23 @@ class SFAuth:
1165
1178
  ]
1166
1179
 
1167
1180
  return combined_response or None
1181
+
1182
+ def _debug_cleanup_apex_logs(self):
1183
+ """
1184
+ This function performs cleanup operations for Apex debug logs.
1185
+ """
1186
+ apex_logs = self.query("SELECT Id FROM ApexLog ORDER BY LogLength DESC")
1187
+ if apex_logs and apex_logs.get("records"):
1188
+ log_ids = [log["Id"] for log in apex_logs["records"]]
1189
+ if log_ids:
1190
+ delete_response = self.cdelete(log_ids)
1191
+ logger.debug("Deleted Apex logs: %s", delete_response)
1192
+ else:
1193
+ logger.debug("No Apex logs found to delete.")
1194
+
1195
+ def debug_cleanup(self, apex_logs: bool = True) -> None:
1196
+ """
1197
+ Perform cleanup operations for Apex debug logs.
1198
+ """
1199
+ if apex_logs:
1200
+ self._debug_cleanup_apex_logs()
@@ -0,0 +1,67 @@
1
+ import os
2
+ import sys
3
+ from pathlib import Path
4
+ from datetime import datetime, timedelta
5
+
6
+ import pytest
7
+
8
+ # --- Setup local import path ---
9
+ project_root = Path(__file__).resolve().parents[1]
10
+ src_path = project_root / "src"
11
+ sys.path.insert(0, str(src_path))
12
+ from sfq import SFAuth # noqa: E402
13
+
14
+
15
+ @pytest.fixture(scope="module")
16
+ def sf_instance():
17
+ required_env_vars = [
18
+ "SF_INSTANCE_URL",
19
+ "SF_CLIENT_ID",
20
+ "SF_CLIENT_SECRET",
21
+ "SF_REFRESH_TOKEN",
22
+ ]
23
+
24
+ missing_vars = [var for var in required_env_vars if not os.getenv(var)]
25
+ if missing_vars:
26
+ pytest.fail(f"Missing required env vars: {', '.join(missing_vars)}")
27
+
28
+ sf = SFAuth(
29
+ instance_url=os.getenv("SF_INSTANCE_URL"),
30
+ client_id=os.getenv("SF_CLIENT_ID"),
31
+ client_secret=os.getenv("SF_CLIENT_SECRET"),
32
+ refresh_token=os.getenv("SF_REFRESH_TOKEN"),
33
+ )
34
+ return sf
35
+
36
+ def test_debug_cleanup(sf_instance, already_executed: bool = False):
37
+ """
38
+ Test the debug_cleanup method of SFAuth.
39
+ This test will check if the method can be called without errors.
40
+ """
41
+ apex_logs = sf_instance.query("SELECT Id FROM ApexLog LIMIT 1")
42
+ apex_log_count = len(apex_logs.get("records", []))
43
+ if apex_log_count == 0:
44
+ # OK, so we need to create an Apex log to test cleanup
45
+ # To do this, let's execute a simple Apex anonymous block
46
+ import http.client
47
+ conn = http.client.HTTPSConnection(sf_instance.instance_url.replace("https://", ""))
48
+ conn.request(
49
+ "GET",
50
+ '/services/data/v64.0/tooling/executeAnonymous/?anonymousBody=Long%20currentUnixTime%20%3D%20DateTime.now().getTime()%20%2F%201000%3B',
51
+ headers={
52
+ "Authorization": f"Bearer {sf_instance.access_token}",
53
+ "Content-Type": "application/json"
54
+ }
55
+ )
56
+ response = conn.getresponse()
57
+ if response.status != http.client.OK:
58
+ pytest.fail(f"Failed to create Apex logs: {response.reason}")
59
+ if already_executed:
60
+ pytest.fail("ApexLog creation failed, cannot evaluate Apex log test.")
61
+ return test_debug_cleanup(sf_instance, already_executed=True)
62
+
63
+ sf_instance.debug_cleanup(apex_logs=True)
64
+
65
+ apex_logs = sf_instance.query("SELECT Id FROM ApexLog LIMIT 1")
66
+ apex_log_count = len(apex_logs.get("records", []))
67
+ assert apex_log_count == 0, "Apex logs were not cleaned up successfully."
@@ -3,5 +3,5 @@ requires-python = ">=3.9"
3
3
 
4
4
  [[package]]
5
5
  name = "sfq"
6
- version = "0.0.29"
6
+ version = "0.0.30"
7
7
  source = { editable = "." }
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