alita-sdk 0.3.428__py3-none-any.whl → 0.3.428b2__py3-none-any.whl

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.

Potentially problematic release.


This version of alita-sdk might be problematic. Click here for more details.

@@ -5,6 +5,7 @@ import re
5
5
  from traceback import format_exc
6
6
  from typing import Any, Optional
7
7
 
8
+ import requests
8
9
  import swagger_client
9
10
  from langchain_core.tools import ToolException
10
11
  from pydantic import Field, PrivateAttr, model_validator, create_model, SecretStr
@@ -194,11 +195,11 @@ class QtestApiWrapper(BaseToolApiWrapper):
194
195
 
195
196
  def __get_field_definitions_cached(self) -> dict:
196
197
  """Get field definitions with session-level caching.
197
-
198
+
198
199
  Field definitions are cached for the lifetime of this wrapper instance.
199
200
  If project field configuration changes, call refresh_field_definitions_cache()
200
201
  to reload the definitions.
201
-
202
+
202
203
  Returns:
203
204
  dict: Field definitions mapping
204
205
  """
@@ -208,11 +209,11 @@ class QtestApiWrapper(BaseToolApiWrapper):
208
209
 
209
210
  def refresh_field_definitions_cache(self) -> dict:
210
211
  """Manually refresh the field definitions cache.
211
-
212
+
212
213
  Call this method if project field configuration has been updated
213
214
  (new fields added, dropdown values changed, etc.) and you need to
214
215
  reload the definitions within the same agent session.
215
-
216
+
216
217
  Returns:
217
218
  dict: Freshly loaded field definitions
218
219
  """
@@ -223,15 +224,15 @@ class QtestApiWrapper(BaseToolApiWrapper):
223
224
  base_properties: list = None) -> list:
224
225
  """
225
226
  Convert user-friendly property names/values to QTest API PropertyResource format.
226
-
227
+
227
228
  Args:
228
229
  test_case_data: Dict with property names as keys (e.g., {"Status": "New", "Priority": "High"})
229
230
  field_definitions: Output from __get_project_field_definitions()
230
231
  base_properties: Existing properties from a test case (for updates, optional)
231
-
232
+
232
233
  Returns:
233
234
  list[PropertyResource]: Properties ready for API submission
234
-
235
+
235
236
  Raises:
236
237
  ValueError: If any field names are unknown or values are invalid (shows ALL errors)
237
238
  """
@@ -247,32 +248,32 @@ class QtestApiWrapper(BaseToolApiWrapper):
247
248
  'field_value': prop['field_value'],
248
249
  'field_value_name': prop.get('field_value_name')
249
250
  }
250
-
251
+
251
252
  # Collect ALL validation errors before raising
252
253
  validation_errors = []
253
-
254
+
254
255
  # Map incoming properties from test_case_data
255
256
  for field_name, field_value in test_case_data.items():
256
257
  # Skip non-property fields (these are handled separately)
257
258
  if field_name in ['Name', 'Description', 'Precondition', 'Steps', 'Id', QTEST_ID]:
258
259
  continue
259
-
260
+
260
261
  # Skip None or empty string values (don't update these fields)
261
262
  if field_value is None or field_value == '':
262
263
  continue
263
-
264
+
264
265
  # Validate field exists in project - STRICT validation
265
266
  if field_name not in field_definitions:
266
267
  validation_errors.append(
267
268
  f"❌ Unknown field '{field_name}' - not defined in project configuration"
268
269
  )
269
270
  continue # Skip to next field, keep collecting errors
270
-
271
+
271
272
  field_def = field_definitions[field_name]
272
273
  field_id = field_def['field_id']
273
274
  data_type = field_def.get('data_type')
274
275
  is_multiple = field_def.get('multiple', False)
275
-
276
+
276
277
  # Normalize field_value to list for consistent processing
277
278
  # Multi-select fields can receive: "value", ["value1", "value2"], or ["value1"]
278
279
  # Single-select fields: "value" only
@@ -282,13 +283,13 @@ class QtestApiWrapper(BaseToolApiWrapper):
282
283
  else:
283
284
  # Single-select: keep as single value
284
285
  values_to_process = [field_value]
285
-
286
+
286
287
  # Validate value(s) for dropdown fields (only if field has allowed values)
287
288
  if field_def['values']:
288
289
  # Field has allowed values (dropdown/combobox/user fields) - validate strictly
289
290
  value_ids = []
290
291
  value_names = []
291
-
292
+
292
293
  for single_value in values_to_process:
293
294
  if single_value not in field_def['values']:
294
295
  available = ", ".join(sorted(field_def['values'].keys()))
@@ -297,15 +298,15 @@ class QtestApiWrapper(BaseToolApiWrapper):
297
298
  f"Allowed values: {available}"
298
299
  )
299
300
  continue # Skip this value, but continue validating others
300
-
301
+
301
302
  # Valid value - add to lists
302
303
  value_ids.append(field_def['values'][single_value])
303
304
  value_names.append(single_value)
304
-
305
+
305
306
  # If all values were invalid, skip this field
306
307
  if not value_ids:
307
308
  continue
308
-
309
+
309
310
  # Format based on field type and value count
310
311
  if is_multiple and len(value_ids) == 1:
311
312
  # Single value in multi-select field: bracketed string "[419950]"
@@ -326,7 +327,7 @@ class QtestApiWrapper(BaseToolApiWrapper):
326
327
  # No validation needed - users can write anything (by design)
327
328
  field_value_id = field_value
328
329
  field_value_name = field_value if isinstance(field_value, str) else None
329
-
330
+
330
331
  # Update or add property (only if no errors for this field)
331
332
  props_dict[field_name] = {
332
333
  'field_id': field_id,
@@ -334,7 +335,7 @@ class QtestApiWrapper(BaseToolApiWrapper):
334
335
  'field_value': field_value_id,
335
336
  'field_value_name': field_value_name
336
337
  }
337
-
338
+
338
339
  # If ANY validation errors found, raise comprehensive error with all issues
339
340
  if validation_errors:
340
341
  available_fields = ", ".join(sorted(field_definitions.keys()))
@@ -345,7 +346,7 @@ class QtestApiWrapper(BaseToolApiWrapper):
345
346
  f"💡 Tip: Use 'get_all_test_cases_fields_for_project' tool to see all fields with their allowed values."
346
347
  )
347
348
  raise ValueError(error_msg)
348
-
349
+
349
350
  # Convert to PropertyResource list, filtering out special fields
350
351
  result = []
351
352
  for field_name, prop_data in props_dict.items():
@@ -357,25 +358,25 @@ class QtestApiWrapper(BaseToolApiWrapper):
357
358
  field_value=prop_data['field_value'],
358
359
  field_value_name=prop_data.get('field_value_name')
359
360
  ))
360
-
361
+
361
362
  return result
362
363
 
363
364
  def __build_body_for_create_test_case(self, test_cases_data: list[dict],
364
365
  folder_to_place_test_cases_to: str = '') -> list:
365
366
  # Get field definitions for property mapping (cached for session)
366
367
  field_definitions = self.__get_field_definitions_cached()
367
-
368
+
368
369
  modules = self._parse_modules()
369
370
  parent_id = ''.join(str(module['module_id']) for module in modules if
370
371
  folder_to_place_test_cases_to and module['full_module_name'] == folder_to_place_test_cases_to)
371
-
372
+
372
373
  bodies = []
373
374
  for test_case in test_cases_data:
374
375
  # Map properties from user format to API format
375
376
  props = self.__map_properties_to_api_format(test_case, field_definitions)
376
-
377
+
377
378
  body = swagger_client.TestCaseWithCustomFieldResource(properties=props)
378
-
379
+
379
380
  # Only set fields if they are explicitly provided in the input
380
381
  # This prevents overwriting existing values with None during partial updates
381
382
  if 'Name' in test_case:
@@ -384,10 +385,10 @@ class QtestApiWrapper(BaseToolApiWrapper):
384
385
  body.precondition = test_case['Precondition']
385
386
  if 'Description' in test_case:
386
387
  body.description = test_case['Description']
387
-
388
+
388
389
  if parent_id:
389
390
  body.parent_id = parent_id
390
-
391
+
391
392
  # Only set test_steps if Steps are provided in the input
392
393
  # This prevents overwriting existing steps during partial updates
393
394
  if 'Steps' in test_case and test_case['Steps'] is not None:
@@ -397,7 +398,7 @@ class QtestApiWrapper(BaseToolApiWrapper):
397
398
  swagger_client.TestStepResource(description=step.get('Test Step Description'),
398
399
  expected=step.get('Test Step Expected Result')))
399
400
  body.test_steps = test_steps_resources
400
-
401
+
401
402
  bodies.append(body)
402
403
  return bodies
403
404
 
@@ -414,10 +415,147 @@ class QtestApiWrapper(BaseToolApiWrapper):
414
415
  Exception: \n {stacktrace}""")
415
416
  return modules
416
417
 
418
+ def __get_field_definitions_from_properties_api(self) -> dict:
419
+ """
420
+ Fallback method: Get field definitions using /properties and /properties-info APIs.
421
+
422
+ These APIs don't require Field Management permission and are available to all users.
423
+ Requires 2 API calls + 1 search to get a test case ID.
424
+
425
+ Returns:
426
+ dict: Same structure as __get_project_field_definitions()
427
+ """
428
+ logger.info(
429
+ "Using properties API fallback (no Field Management permission). "
430
+ "This requires getting a template test case first."
431
+ )
432
+
433
+ # Step 1: Get any test case ID to query properties
434
+ search_instance = swagger_client.SearchApi(self._client)
435
+ body = swagger_client.ArtifactSearchParams(
436
+ object_type='test-cases',
437
+ fields=['*'],
438
+ query='' # Empty query returns all test cases
439
+ )
440
+
441
+ try:
442
+ # Search for any test case - just need one
443
+ response = search_instance.search_artifact(
444
+ self.qtest_project_id,
445
+ body,
446
+ page_size=1,
447
+ page=1
448
+ )
449
+ except ApiException as e:
450
+ stacktrace = format_exc()
451
+ logger.error(f"Failed to find test case for properties API: {stacktrace}")
452
+ raise ValueError(
453
+ f"Cannot find any test case to query field definitions. "
454
+ f"Please create at least one test case in project {self.qtest_project_id}"
455
+ ) from e
456
+
457
+ if not response or not response.get('items') or len(response['items']) == 0:
458
+ raise ValueError(
459
+ f"No test cases found in project {self.qtest_project_id}. "
460
+ f"Please create at least one test case to retrieve field definitions."
461
+ )
462
+
463
+ test_case_id = response['items'][0]['id']
464
+ logger.info(f"Using test case ID {test_case_id} to retrieve field definitions")
465
+
466
+ # Step 2: Call /properties API
467
+ headers = {
468
+ "Authorization": f"Bearer {self.qtest_api_token.get_secret_value()}"
469
+ }
470
+
471
+ properties_url = f"{self.base_url}/api/v3/projects/{self.qtest_project_id}/test-cases/{test_case_id}/properties"
472
+ properties_info_url = f"{self.base_url}/api/v3/projects/{self.qtest_project_id}/test-cases/{test_case_id}/properties-info"
473
+
474
+ try:
475
+ # Get properties with current values and field metadata
476
+ props_response = requests.get(
477
+ properties_url,
478
+ headers=headers,
479
+ params={'calledBy': 'testcase_properties'}
480
+ )
481
+ props_response.raise_for_status()
482
+ properties_data = props_response.json()
483
+
484
+ # Get properties-info with data types and allowed values
485
+ info_response = requests.get(properties_info_url, headers=headers)
486
+ info_response.raise_for_status()
487
+ info_data = info_response.json()
488
+
489
+ except requests.exceptions.RequestException as e:
490
+ stacktrace = format_exc()
491
+ logger.error(f"Failed to call properties API: {stacktrace}")
492
+ raise ValueError(
493
+ f"Unable to retrieve field definitions using properties API. "
494
+ f"Error: {stacktrace}"
495
+ ) from e
496
+
497
+ # Step 3: Build field mapping by merging both responses
498
+ field_mapping = {}
499
+
500
+ # Create lookup by field ID from properties-info
501
+ metadata_by_id = {item['id']: item for item in info_data['metadata']}
502
+
503
+ # Data type mapping to determine 'multiple' flag
504
+ MULTI_SELECT_TYPES = {
505
+ 'UserListDataType',
506
+ 'MultiSelectionDataType',
507
+ 'CheckListDataType'
508
+ }
509
+
510
+ USER_FIELD_TYPES = {'UserListDataType'}
511
+
512
+ # System fields to exclude (same as in property mapping)
513
+ excluded_fields = {'Shared', 'Projects Shared to'}
514
+
515
+ for prop in properties_data:
516
+ field_name = prop.get('name')
517
+ field_id = prop.get('id')
518
+
519
+ if not field_name or field_name in excluded_fields:
520
+ continue
521
+
522
+ # Get metadata for this field
523
+ metadata = metadata_by_id.get(field_id, {})
524
+ data_type_str = metadata.get('data_type')
525
+
526
+ # Determine data_type number (5 for user fields, None for others)
527
+ data_type = 5 if data_type_str in USER_FIELD_TYPES else None
528
+
529
+ # Determine if multi-select
530
+ is_multiple = data_type_str in MULTI_SELECT_TYPES
531
+
532
+ field_mapping[field_name] = {
533
+ 'field_id': field_id,
534
+ 'required': prop.get('required', False),
535
+ 'data_type': data_type,
536
+ 'multiple': is_multiple,
537
+ 'values': {}
538
+ }
539
+
540
+ # Map allowed values from metadata
541
+ allowed_values = metadata.get('allowed_values', [])
542
+ for allowed_val in allowed_values:
543
+ value_text = allowed_val.get('value_text')
544
+ value_id = allowed_val.get('id')
545
+ if value_text and value_id:
546
+ field_mapping[field_name]['values'][value_text] = value_id
547
+
548
+ logger.info(
549
+ f"Retrieved {len(field_mapping)} field definitions using properties API. "
550
+ f"This method works for all users without Field Management permission."
551
+ )
552
+
553
+ return field_mapping
554
+
417
555
  def __get_project_field_definitions(self) -> dict:
418
556
  """
419
557
  Get structured field definitions for test cases in the project.
420
-
558
+
421
559
  Returns:
422
560
  dict: Mapping of field names to their IDs and allowed values.
423
561
  Example: {
@@ -435,15 +573,24 @@ class QtestApiWrapper(BaseToolApiWrapper):
435
573
  """
436
574
  fields_api = self.__instantiate_fields_api_instance()
437
575
  qtest_object = 'test-cases'
438
-
576
+
439
577
  try:
440
578
  fields = fields_api.get_fields(self.qtest_project_id, qtest_object)
441
579
  except ApiException as e:
580
+ # Check if permission denied (403) - use fallback
581
+ if e.status == 403:
582
+ logger.warning(
583
+ "get_fields permission denied (Field Management permission required). "
584
+ "Using properties API fallback..."
585
+ )
586
+ return self.__get_field_definitions_from_properties_api()
587
+
588
+ # Other API errors
442
589
  stacktrace = format_exc()
443
590
  logger.error(f"Exception when calling FieldAPI->get_fields:\n {stacktrace}")
444
591
  raise ValueError(
445
592
  f"Unable to get test case fields for project {self.qtest_project_id}. Exception: \n {stacktrace}")
446
-
593
+
447
594
  # Build structured mapping
448
595
  field_mapping = {}
449
596
  for field in fields:
@@ -455,7 +602,7 @@ class QtestApiWrapper(BaseToolApiWrapper):
455
602
  'multiple': getattr(field, 'multiple', False), # True = multi-select, needs array format
456
603
  'values': {}
457
604
  }
458
-
605
+
459
606
  # Map allowed values if field has them (dropdown/combobox/user fields)
460
607
  # Only include active values (is_active=True)
461
608
  if hasattr(field, 'allowed_values') and field.allowed_values:
@@ -463,38 +610,38 @@ class QtestApiWrapper(BaseToolApiWrapper):
463
610
  # Skip inactive values (deleted/deprecated options)
464
611
  if hasattr(allowed_value, 'is_active') and not allowed_value.is_active:
465
612
  continue
466
-
613
+
467
614
  # AllowedValueResource has 'label' for the display name and 'value' for the ID
468
615
  # Note: 'value' is the field_value, not 'id'
469
616
  # For user fields (data_type=5), label is user name and value is user ID
470
617
  value_label = allowed_value.label
471
618
  value_id = allowed_value.value
472
619
  field_mapping[field_name]['values'][value_label] = value_id
473
-
620
+
474
621
  return field_mapping
475
622
 
476
623
  def __format_field_info_for_display(self, field_definitions: dict) -> str:
477
624
  """
478
625
  Format field definitions in human-readable format for LLM.
479
-
626
+
480
627
  Args:
481
628
  field_definitions: Output from __get_project_field_definitions()
482
-
629
+
483
630
  Returns:
484
631
  Formatted string with field information
485
632
  """
486
633
  output = [f"Available Test Case Fields for Project {self.qtest_project_id}:\n"]
487
-
634
+
488
635
  for field_name, field_info in sorted(field_definitions.items()):
489
636
  required_marker = " (Required)" if field_info.get('required') else ""
490
637
  output.append(f"\n{field_name}{required_marker}:")
491
-
638
+
492
639
  if field_info.get('values'):
493
640
  for value_name, value_id in sorted(field_info['values'].items()):
494
641
  output.append(f" - {value_name} (id: {value_id})")
495
642
  else:
496
643
  output.append(" Type: text")
497
-
644
+
498
645
  output.append("\n\nUse these exact value names when creating or updating test cases.")
499
646
  return ''.join(output)
500
647
 
@@ -502,12 +649,12 @@ class QtestApiWrapper(BaseToolApiWrapper):
502
649
  """
503
650
  Get formatted information about available test case fields and their values.
504
651
  This method is exposed as a tool for LLM to query field information.
505
-
652
+
506
653
  Args:
507
654
  force_refresh: If True, reload field definitions from API instead of using cache.
508
655
  Use this if project configuration has changed (new fields added,
509
656
  dropdown values modified, etc.).
510
-
657
+
511
658
  Returns:
512
659
  Formatted string with field names and allowed values
513
660
  """
@@ -555,10 +702,10 @@ class QtestApiWrapper(BaseToolApiWrapper):
555
702
 
556
703
  def __parse_data(self, response_to_parse: dict, parsed_data: list, extract_images: bool=False, prompt: str=None):
557
704
  import html
558
-
559
- # Get field definitions to ensure all fields are included (uses cached version)
560
- field_definitions = self.__get_field_definitions_cached()
561
-
705
+
706
+ # PERMISSION-FREE: Parse properties directly from API response
707
+ # No get_fields call needed - works for all users
708
+
562
709
  for item in response_to_parse['items']:
563
710
  # Start with core fields (always present)
564
711
  parsed_data_row = {
@@ -573,31 +720,17 @@ class QtestApiWrapper(BaseToolApiWrapper):
573
720
  'Test Step Expected Result': self._process_image(step[1]['expected'], extract_images, prompt)
574
721
  }, enumerate(item['test_steps']))),
575
722
  }
576
-
577
- # Dynamically add all custom fields from project configuration
578
- # This ensures consistency and includes fields even if they have null/empty values
579
- for field_name in field_definitions.keys():
580
- field_def = field_definitions[field_name]
581
- is_multiple = field_def.get('multiple', False)
582
-
583
- # Find the property value in the response (if exists)
584
- field_value = None
585
- for prop in item['properties']:
586
- if prop['field_name'] == field_name:
587
- # Use field_value_name if available (for dropdowns), otherwise field_value
588
- field_value = prop.get('field_value_name') or prop.get('field_value') or ''
589
- break
590
-
591
- # Format based on field type
592
- if is_multiple and (field_value is None or field_value == ''):
593
- # Multi-select field with no value: show empty array with hint
594
- parsed_data_row[field_name] = '[] (multi-select)'
595
- elif field_value is not None:
596
- parsed_data_row[field_name] = field_value
597
- else:
598
- # Regular field with no value
599
- parsed_data_row[field_name] = ''
600
-
723
+
724
+ # Add custom fields directly from API response properties
725
+ for prop in item['properties']:
726
+ field_name = prop.get('field_name')
727
+ if not field_name:
728
+ continue
729
+
730
+ # Use field_value_name if available (for dropdowns/users), otherwise field_value
731
+ field_value = prop.get('field_value_name') or prop.get('field_value') or ''
732
+ parsed_data_row[field_name] = field_value
733
+
601
734
  parsed_data.append(parsed_data_row)
602
735
 
603
736
  def _process_image(self, content: str, extract: bool=False, prompt: str=None):
@@ -657,20 +790,20 @@ class QtestApiWrapper(BaseToolApiWrapper):
657
790
 
658
791
  def __find_qtest_requirement_id_by_id(self, requirement_id: str) -> int:
659
792
  """Search for requirement's internal QTest ID using requirement ID (RQ-xxx format).
660
-
793
+
661
794
  Args:
662
795
  requirement_id: Requirement ID in format RQ-123
663
-
796
+
664
797
  Returns:
665
798
  int: Internal QTest ID for the requirement
666
-
799
+
667
800
  Raises:
668
801
  ValueError: If requirement is not found
669
802
  """
670
803
  dql = f"Id = '{requirement_id}'"
671
804
  search_instance: SearchApi = swagger_client.SearchApi(self._client)
672
805
  body = swagger_client.ArtifactSearchParams(object_type='requirements', fields=['*'], query=dql)
673
-
806
+
674
807
  try:
675
808
  response = search_instance.search_artifact(self.qtest_project_id, body)
676
809
  if response['total'] == 0:
@@ -705,13 +838,13 @@ class QtestApiWrapper(BaseToolApiWrapper):
705
838
 
706
839
  def _get_jira_requirement_id(self, jira_issue_id: str) -> int:
707
840
  """Search for requirement id using the linked jira_issue_id.
708
-
841
+
709
842
  Args:
710
843
  jira_issue_id: External Jira issue ID (e.g., PLAN-128)
711
-
844
+
712
845
  Returns:
713
846
  int: Internal QTest ID for the Jira requirement
714
-
847
+
715
848
  Raises:
716
849
  ValueError: If Jira requirement is not found in QTest
717
850
  """
@@ -726,11 +859,11 @@ class QtestApiWrapper(BaseToolApiWrapper):
726
859
 
727
860
  def link_tests_to_jira_requirement(self, requirement_external_id: str, json_list_of_test_case_ids: str) -> str:
728
861
  """Link test cases to external Jira requirement.
729
-
862
+
730
863
  Args:
731
864
  requirement_external_id: Jira issue ID (e.g., PLAN-128)
732
865
  json_list_of_test_case_ids: JSON array string of test case IDs (e.g., '["TC-123", "TC-234"]')
733
-
866
+
734
867
  Returns:
735
868
  Success message with linked test case IDs
736
869
  """
@@ -743,10 +876,10 @@ class QtestApiWrapper(BaseToolApiWrapper):
743
876
 
744
877
  try:
745
878
  response = link_object_api_instance.link_artifacts(
746
- self.qtest_project_id,
879
+ self.qtest_project_id,
747
880
  object_id=requirement_id,
748
881
  type=linked_type,
749
- object_type=source_type,
882
+ object_type=source_type,
750
883
  body=qtest_test_case_ids
751
884
  )
752
885
  linked_test_cases = [link.pid for link in response[0].objects]
@@ -765,14 +898,14 @@ class QtestApiWrapper(BaseToolApiWrapper):
765
898
 
766
899
  def link_tests_to_qtest_requirement(self, requirement_id: str, json_list_of_test_case_ids: str) -> str:
767
900
  """Link test cases to internal QTest requirement.
768
-
901
+
769
902
  Args:
770
903
  requirement_id: QTest requirement ID in format RQ-123
771
904
  json_list_of_test_case_ids: JSON array string of test case IDs (e.g., '["TC-123", "TC-234"]')
772
-
905
+
773
906
  Returns:
774
907
  Success message with linked test case IDs
775
-
908
+
776
909
  Raises:
777
910
  ValueError: If requirement or test cases are not found
778
911
  ToolException: If linking fails
@@ -780,11 +913,11 @@ class QtestApiWrapper(BaseToolApiWrapper):
780
913
  link_object_api_instance = swagger_client.ObjectLinkApi(self._client)
781
914
  source_type = "requirements"
782
915
  linked_type = "test-cases"
783
-
916
+
784
917
  # Parse and convert test case IDs
785
918
  test_case_ids = json.loads(json_list_of_test_case_ids)
786
919
  qtest_test_case_ids = [self.__find_qtest_id_by_test_id(tc_id) for tc_id in test_case_ids]
787
-
920
+
788
921
  # Get internal QTest ID for the requirement
789
922
  qtest_requirement_id = self.__find_qtest_requirement_id_by_id(requirement_id)
790
923
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.428
3
+ Version: 0.3.428b2
4
4
  Summary: SDK for building langchain agents using resources from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedj27@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -303,7 +303,7 @@ alita_sdk/tools/postman/postman_analysis.py,sha256=ckc2BfKEop0xnmLPksVRE_Y94ixuq
303
303
  alita_sdk/tools/pptx/__init__.py,sha256=vVUrWnj7KWJgEk9oxGSsCAQ2SMSXrp_SFOdUHYQKcAo,3444
304
304
  alita_sdk/tools/pptx/pptx_wrapper.py,sha256=yyCYcTlIY976kJ4VfPo4dyxj4yeii9j9TWP6W8ZIpN8,29195
305
305
  alita_sdk/tools/qtest/__init__.py,sha256=Jf0xo5S_4clXR2TfCbJbB1sFgCbcFQRM-YYX2ltWBzo,4461
306
- alita_sdk/tools/qtest/api_wrapper.py,sha256=5YJPcEGUT_V_SdgiYBoPDJHTEDfCrDgzoXTdXuGoH4I,46652
306
+ alita_sdk/tools/qtest/api_wrapper.py,sha256=Cds_TnyWhR-2NaoHio9ePYMLT7RGS0nx20KAqifIOWk,50977
307
307
  alita_sdk/tools/qtest/tool.py,sha256=kKzNPS4fUC76WQQttQ6kdVANViHEvKE8Kf174MQiNYU,562
308
308
  alita_sdk/tools/rally/__init__.py,sha256=2BPPXJxAOKgfmaxVFVvxndfK0JxOXDLkoRmzu2dUwOE,3512
309
309
  alita_sdk/tools/rally/api_wrapper.py,sha256=mouzU6g0KML4UNapdk0k6Q0pU3MpJuWnNo71n9PSEHM,11752
@@ -353,8 +353,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
353
353
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
354
354
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
355
355
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
356
- alita_sdk-0.3.428.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
- alita_sdk-0.3.428.dist-info/METADATA,sha256=ej9BznzDUgSAEvLoIGgbx97Sw4qGYdHkqAx3wyTN95E,19071
358
- alita_sdk-0.3.428.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
- alita_sdk-0.3.428.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
- alita_sdk-0.3.428.dist-info/RECORD,,
356
+ alita_sdk-0.3.428b2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
+ alita_sdk-0.3.428b2.dist-info/METADATA,sha256=WmL2Jo4Efefiq86rZ0hYJlMZx-epmDrwx-2qNTaWnEc,19073
358
+ alita_sdk-0.3.428b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
+ alita_sdk-0.3.428b2.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
+ alita_sdk-0.3.428b2.dist-info/RECORD,,