codeflash 0.3.3__tar.gz → 0.3.4__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 (50) hide show
  1. {codeflash-0.3.3 → codeflash-0.3.4}/PKG-INFO +2 -2
  2. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/api/aiservice.py +21 -18
  3. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/api/cfapi.py +8 -4
  4. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/env_utils.py +4 -0
  5. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/discovery/functions_to_optimize.py +13 -5
  6. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/main.py +3 -0
  7. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/optimization/function_context.py +25 -20
  8. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/result/create_pr.py +2 -6
  9. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/comparator.py +39 -2
  10. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/parse_test_output.py +4 -3
  11. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/version.py +2 -2
  12. {codeflash-0.3.3 → codeflash-0.3.4}/pyproject.toml +3 -3
  13. {codeflash-0.3.3 → codeflash-0.3.4}/README.md +0 -0
  14. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/LICENSE +0 -0
  15. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/analytics/__init__.py +0 -0
  16. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/analytics/posthog.py +0 -0
  17. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/api/__init__.py +0 -0
  18. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/cli_cmds/__init__.py +0 -0
  19. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/cli_cmds/cli.py +0 -0
  20. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/cli_cmds/cmd_init.py +0 -0
  21. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/cli_cmds/logging_config.py +0 -0
  22. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/cli_cmds/workflows/codeflash-optimize.yaml +0 -0
  23. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/__init__.py +0 -0
  24. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/code_extractor.py +0 -0
  25. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/code_replacer.py +0 -0
  26. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/code_utils.py +0 -0
  27. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/config_consts.py +0 -0
  28. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/config_parser.py +0 -0
  29. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/git_utils.py +0 -0
  30. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/instrument_existing_tests.py +0 -0
  31. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/linter.py +0 -0
  32. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/sqlalchemy_utils.py +0 -0
  33. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/code_utils/time_utils.py +0 -0
  34. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/discovery/__init__.py +0 -0
  35. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/discovery/discover_unit_tests.py +0 -0
  36. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/github/PrComment.py +0 -0
  37. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/github/__init__.py +0 -0
  38. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/optimization/__init__.py +0 -0
  39. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/result/__init__.py +0 -0
  40. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/result/explanation.py +0 -0
  41. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/tracing/__init__.py +0 -0
  42. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/tracing/replay_test.py +0 -0
  43. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/tracing/tracer.py +0 -0
  44. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/update_license_version.py +0 -0
  45. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/__init__.py +0 -0
  46. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/equivalence.py +0 -0
  47. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/test_results.py +0 -0
  48. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/test_runner.py +0 -0
  49. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/verification_utils.py +0 -0
  50. {codeflash-0.3.3 → codeflash-0.3.4}/codeflash/verification/verifier.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeflash
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: A Code Performance Optimization Library
5
5
  Home-page: https://codeflash.ai
6
6
  Author: CodeFlash Inc.
@@ -20,7 +20,7 @@ Requires-Dist: jedi (>=0.19.0)
20
20
  Requires-Dist: junitparser (>=3.1.0)
21
21
  Requires-Dist: libcst (>=1.0.1)
22
22
  Requires-Dist: posthog (>=3.0.0)
23
- Requires-Dist: pydantic (>=2.5.2,<3.0.0)
23
+ Requires-Dist: pydantic (>=1.10.1)
24
24
  Requires-Dist: pytest (>=7.0.0)
25
25
  Requires-Dist: pytest-timeout (>=2.1.0)
26
26
  Requires-Dist: tiktoken (>=0.3.2)
@@ -1,9 +1,11 @@
1
+ import json
1
2
  import logging
2
3
  import os
3
- import requests
4
- from pydantic import RootModel
5
4
  from typing import Any, Dict, List, Tuple, Optional
6
5
 
6
+ import requests
7
+ from pydantic.json import pydantic_encoder
8
+
7
9
  from codeflash.analytics.posthog import ph
8
10
  from codeflash.code_utils.env_utils import get_codeflash_api_key
9
11
  from codeflash.discovery.functions_to_optimize import FunctionToOptimize
@@ -23,19 +25,20 @@ def make_ai_service_request(
23
25
  ) -> requests.Response:
24
26
  """
25
27
  Make an API request to the given endpoint on the AI service.
26
-
27
- Parameters:
28
- - endpoint (str): The endpoint to call, e.g., "/optimize".
29
- - method (str): The HTTP method to use, e.g., "POST".
30
- - data (Dict[str, Any]): The data to send in the request.
31
-
32
- Returns:
33
- - requests.Response: The response from the API.
28
+ :param endpoint: The endpoint to call, e.g., "/optimize".
29
+ :param method: The HTTP method to use ('GET' or 'POST').
30
+ :param payload: Optional JSON payload to include in the POST request body.
31
+ :param timeout: The timeout for the request.
32
+ :return: The response object from the API.
34
33
  """
35
34
  url = f"{AI_SERVICE_BASE_URL}/ai{endpoint}"
36
35
  ai_service_headers = {"Authorization": f"Bearer {get_codeflash_api_key()}"}
37
36
  if method.upper() == "POST":
38
- response = requests.post(url, json=payload, headers=ai_service_headers, timeout=timeout)
37
+ json_payload = json.dumps(payload, indent=None, default=pydantic_encoder)
38
+ ai_service_headers["Content-Type"] = "application/json"
39
+ response = requests.post(
40
+ url, data=json_payload, headers=ai_service_headers, timeout=timeout
41
+ )
39
42
  else:
40
43
  response = requests.get(url, headers=ai_service_headers, timeout=timeout)
41
44
  # response.raise_for_status() # Will raise an HTTPError if the HTTP request returned an unsuccessful status code
@@ -55,10 +58,10 @@ def optimize_python_code(
55
58
  Returns:
56
59
  - List[Tuple[str, str]]: A list of tuples where the first element is the optimized code and the second is the explanation.
57
60
  """
58
- data = {"source_code": source_code, "num_variants": num_variants}
61
+ payload = {"source_code": source_code, "num_variants": num_variants}
59
62
  logging.info(f"Generating optimized candidates ...")
60
63
  try:
61
- response = make_ai_service_request("/optimize", payload=data, timeout=600)
64
+ response = make_ai_service_request("/optimize", payload=payload, timeout=600)
62
65
  except requests.exceptions.RequestException as e:
63
66
  logging.error(f"Error generating optimized candidates: {e}")
64
67
  ph("cli-optimize-error-caught", {"error": str(e)})
@@ -66,6 +69,7 @@ def optimize_python_code(
66
69
 
67
70
  if response.status_code == 200:
68
71
  optimizations = response.json()["optimizations"]
72
+ logging.info(f"Generated {len(optimizations)} candidates.")
69
73
  return [(opt["source_code"], opt["explanation"]) for opt in optimizations]
70
74
  else:
71
75
  try:
@@ -108,11 +112,9 @@ def generate_regression_tests(
108
112
  "pytest",
109
113
  "unittest",
110
114
  ], f"Invalid test framework, got {test_framework} but expected 'pytest' or 'unittest'"
111
- data = {
115
+ payload = {
112
116
  "source_code_being_tested": source_code_being_tested,
113
- "function_to_optimize": RootModel[FunctionToOptimize](function_to_optimize).model_dump(
114
- mode="json"
115
- ),
117
+ "function_to_optimize": function_to_optimize,
116
118
  "dependent_function_names": dependent_function_names,
117
119
  "module_path": module_path,
118
120
  "test_module_path": test_module_path,
@@ -120,7 +122,7 @@ def generate_regression_tests(
120
122
  "test_timeout": test_timeout,
121
123
  }
122
124
  try:
123
- response = make_ai_service_request("/testgen", payload=data, timeout=600)
125
+ response = make_ai_service_request("/testgen", payload=payload, timeout=600)
124
126
  except requests.exceptions.RequestException as e:
125
127
  logging.error(f"Error generating tests: {e}")
126
128
  ph("cli-testgen-error-caught", {"error": str(e)})
@@ -130,6 +132,7 @@ def generate_regression_tests(
130
132
 
131
133
  if response.status_code == 200:
132
134
  response_json = response.json()
135
+ logging.info(f"Generated tests for function {function_to_optimize.function_name}")
133
136
  return response_json["generated_tests"], response_json["instrumented_tests"]
134
137
  else:
135
138
  try:
@@ -1,9 +1,11 @@
1
+ import json
1
2
  import logging
2
3
  import os
3
4
  from functools import lru_cache
4
5
  from typing import Optional, Dict, Any
5
6
 
6
7
  import requests
8
+ from pydantic.json import pydantic_encoder
7
9
  from requests import Response
8
10
 
9
11
  from codeflash.code_utils.env_utils import get_codeflash_api_key
@@ -21,15 +23,17 @@ def make_cfapi_request(
21
23
  ) -> requests.Response:
22
24
  """
23
25
  Make an HTTP request using the specified method, URL, headers, and JSON payload.
24
- :param endpoint: The URL to send the request to.
26
+ :param endpoint: The endpoint URL to send the request to.
25
27
  :param method: The HTTP method to use ('GET', 'POST', etc.).
26
- :param payload: Optional JSON payload to include in the request body.
27
- :return: The response object.
28
+ :param payload: Optional JSON payload to include in the POST request body.
29
+ :return: The response object from the API.
28
30
  """
29
31
  url = f"{CFAPI_BASE_URL}/cfapi{endpoint}"
30
32
  cfapi_headers = {"Authorization": f"Bearer {get_codeflash_api_key()}"}
31
33
  if method.upper() == "POST":
32
- response = requests.post(url, json=payload, headers=cfapi_headers)
34
+ json_payload = json.dumps(payload, indent=None, default=pydantic_encoder)
35
+ cfapi_headers["Content-Type"] = "application/json"
36
+ response = requests.post(url, data=json_payload, headers=cfapi_headers)
33
37
  else:
34
38
  response = requests.get(url, headers=cfapi_headers)
35
39
  return response
@@ -1,8 +1,10 @@
1
1
  import logging
2
2
  import os
3
+ from functools import lru_cache
3
4
  from typing import Optional
4
5
 
5
6
 
7
+ @lru_cache(maxsize=1)
6
8
  def get_codeflash_api_key() -> Optional[str]:
7
9
  api_key = os.environ.get("CODEFLASH_API_KEY")
8
10
  if not api_key:
@@ -33,11 +35,13 @@ def ensure_codeflash_api_key() -> bool:
33
35
  return True
34
36
 
35
37
 
38
+ @lru_cache(maxsize=1)
36
39
  def get_codeflash_org_key() -> Optional[str]:
37
40
  api_key = os.environ.get("CODEFLASH_ORG_KEY")
38
41
  return api_key
39
42
 
40
43
 
44
+ @lru_cache(maxsize=1)
41
45
  def get_pr_number() -> Optional[int]:
42
46
  pr_number = os.environ.get("CODEFLASH_PR_NUMBER")
43
47
  if not pr_number:
@@ -1,12 +1,12 @@
1
1
  import ast
2
+ import libcst as cst
2
3
  import logging
3
4
  import os
5
+ import random
4
6
  from _ast import ClassDef, FunctionDef, AsyncFunctionDef
5
- from typing import Dict, Optional, List, Tuple, Union
6
-
7
- import libcst as cst
8
7
  from libcst import CSTNode
9
8
  from pydantic.dataclasses import dataclass
9
+ from typing import Dict, Optional, List, Tuple, Union
10
10
 
11
11
  from codeflash.code_utils.code_utils import path_belongs_to_site_packages
12
12
  from codeflash.code_utils.git_utils import get_git_diff
@@ -128,7 +128,10 @@ def get_functions_to_optimize_by_file(
128
128
  if only_function_name == fn.function_name:
129
129
  found_function = fn
130
130
  if found_function is None:
131
- raise ValueError(f"Function {only_function_name} not found in file {file}")
131
+ raise ValueError(
132
+ f"Function {only_function_name} not found in file {file} or"
133
+ f" the function does not have a 'return' statement."
134
+ )
132
135
  functions[file] = [found_function]
133
136
  else:
134
137
  logging.info("Finding all functions modified in the current git diff ...")
@@ -170,7 +173,12 @@ def get_all_files_and_functions(module_root_path: str) -> Dict[str, List[Functio
170
173
  file_path = os.path.join(root, file)
171
174
  # Find all the functions in the file
172
175
  functions.update(find_all_functions_in_file(file_path))
173
- return functions
176
+ # Randomize the order of the files to optimize to avoid optimizing the same file in the same order every time.
177
+ # Helpful if an optimize-all run is stuck and we restart it.
178
+ files_list = list(functions.items())
179
+ random.shuffle(files_list)
180
+ functions_shuffled = dict(files_list)
181
+ return functions_shuffled
174
182
 
175
183
 
176
184
  def find_all_functions_in_file(file_path: str) -> Dict[str, List[FunctionToOptimize]]:
@@ -1,3 +1,6 @@
1
+ """Thanks for being curious about how codeflash works! If you might want to work with us on finally making performance a
2
+ solved problem, please reach out to us at careers@codeflash.ai. We're hiring!
3
+ """
1
4
  import concurrent.futures
2
5
  import libcst as cst
3
6
  import logging
@@ -1,12 +1,12 @@
1
1
  import ast
2
- import jedi
3
2
  import logging
4
3
  import os
4
+ from typing import List
5
+
6
+ import jedi
5
7
  import tiktoken
6
8
  from jedi.api.classes import Name
7
- from pydantic import RootModel
8
9
  from pydantic.dataclasses import dataclass
9
- from typing import List
10
10
 
11
11
  from codeflash.code_utils.code_extractor import get_code_no_skeleton, get_code
12
12
  from codeflash.code_utils.code_utils import path_belongs_to_site_packages
@@ -43,11 +43,6 @@ class Source:
43
43
  source_code: str
44
44
 
45
45
 
46
- @dataclass(frozen=True)
47
- class SourceList(RootModel):
48
- root: list[Source]
49
-
50
-
51
46
  def get_type_annotation_context(
52
47
  function: FunctionToOptimize, jedi_script: jedi.Script, project_root_path: str
53
48
  ) -> List[Source]:
@@ -72,12 +67,18 @@ def get_type_annotation_context(
72
67
  name = arg.annotation.id
73
68
  line_no = arg.annotation.lineno
74
69
  col_no = arg.annotation.col_offset
75
- definition: List[Name] = jedi_script.goto(
76
- line=line_no,
77
- column=col_no,
78
- follow_imports=True,
79
- follow_builtin_imports=False,
80
- )
70
+ try:
71
+ definition: List[Name] = jedi_script.goto(
72
+ line=line_no,
73
+ column=col_no,
74
+ follow_imports=True,
75
+ follow_builtin_imports=False,
76
+ )
77
+ except Exception as e:
78
+ logging.error(
79
+ f"Error while getting definition for {name.full_name}: {e}"
80
+ )
81
+ definition = []
81
82
  if definition: # TODO can be multiple definitions
82
83
  definition_path = str(definition[0].module_path)
83
84
  # The definition is part of this project and not defined within the original function
@@ -136,12 +137,16 @@ def get_function_variables_definitions(
136
137
  names.append(ref)
137
138
 
138
139
  for name in names:
139
- definitions: List[Name] = script.goto(
140
- line=name.line,
141
- column=name.column,
142
- follow_imports=True,
143
- follow_builtin_imports=False,
144
- )
140
+ try:
141
+ definitions: List[Name] = script.goto(
142
+ line=name.line,
143
+ column=name.column,
144
+ follow_imports=True,
145
+ follow_builtin_imports=False,
146
+ )
147
+ except Exception as e:
148
+ logging.error(f"Error while getting definition for {name.full_name}: {e}")
149
+ definitions = []
145
150
  if definitions:
146
151
  # TODO: there can be multiple definitions, see how to handle such cases
147
152
  definition_path = str(definitions[0].module_path)
@@ -29,9 +29,7 @@ def check_create_pr(
29
29
  repo=repo,
30
30
  pr_number=pr_number,
31
31
  file_changes={
32
- relative_path: FileDiffContent(
33
- oldContent=original_code, newContent=new_code
34
- ).model_dump(mode="json")
32
+ relative_path: FileDiffContent(oldContent=original_code, newContent=new_code)
35
33
  },
36
34
  pr_comment=PrComment(
37
35
  optimization_explanation=explanation.explanation_message(),
@@ -64,9 +62,7 @@ def check_create_pr(
64
62
  repo=repo,
65
63
  base_branch=base_branch,
66
64
  file_changes={
67
- relative_path: FileDiffContent(
68
- oldContent=original_code, newContent=new_code
69
- ).model_dump(mode="json")
65
+ relative_path: FileDiffContent(oldContent=original_code, newContent=new_code)
70
66
  },
71
67
  pr_comment=PrComment(
72
68
  optimization_explanation=explanation.explanation_message(),
@@ -1,4 +1,5 @@
1
1
  import datetime
2
+ import decimal
2
3
  import logging
3
4
  import math
4
5
  from typing import Any
@@ -15,6 +16,19 @@ try:
15
16
  HAS_SQLALCHEMY = True
16
17
  except ImportError:
17
18
  HAS_SQLALCHEMY = False
19
+ try:
20
+ import scipy
21
+
22
+ HAS_SCIPY = True
23
+ except ImportError:
24
+ HAS_SCIPY = False
25
+
26
+ try:
27
+ import pandas
28
+
29
+ HAS_PANDAS = True
30
+ except ImportError:
31
+ HAS_PANDAS = False
18
32
 
19
33
 
20
34
  def comparator(orig: Any, new: Any) -> bool:
@@ -43,13 +57,14 @@ def comparator(orig: Any, new: Any) -> bool:
43
57
  return False
44
58
  return True
45
59
 
46
- if isinstance(orig, (str, int, bool, complex, type(None))):
60
+ if isinstance(orig, (str, int, bool, complex, type(None), decimal.Decimal)):
47
61
  return orig == new
48
62
  if isinstance(orig, float):
49
63
  if math.isnan(orig) and math.isnan(new):
50
64
  return True
51
65
  return math.isclose(orig, new)
52
- if isinstance(orig, dict):
66
+ # scipy condition because dok_matrix type is also a instance of dict, but dict comparison doesn't work for it
67
+ if isinstance(orig, dict) and not (HAS_SCIPY and isinstance(orig, scipy.sparse.spmatrix)):
53
68
  if len(orig) != len(new):
54
69
  return False
55
70
  for key in orig:
@@ -76,6 +91,28 @@ def comparator(orig: Any, new: Any) -> bool:
76
91
  if HAS_NUMPY and isinstance(orig, (np.integer, np.bool_, np.byte)):
77
92
  return orig == new
78
93
 
94
+ if HAS_SCIPY and isinstance(orig, scipy.sparse.spmatrix):
95
+ if orig.dtype != new.dtype:
96
+ return False
97
+ if orig.get_shape() != new.get_shape():
98
+ return False
99
+ return (orig != new).nnz == 0
100
+
101
+ if HAS_PANDAS and isinstance(
102
+ orig,
103
+ (
104
+ pandas.DataFrame,
105
+ pandas.Series,
106
+ pandas.Index,
107
+ pandas.Categorical,
108
+ pandas.arrays.SparseArray,
109
+ ),
110
+ ):
111
+ return orig.equals(new)
112
+
113
+ if HAS_PANDAS and isinstance(orig, (pandas.CategoricalDtype, pandas.Interval, pandas.Period)):
114
+ return orig == new
115
+
79
116
  # This should be at the end of all numpy checking
80
117
  try:
81
118
  if HAS_NUMPY and np.isnan(orig):
@@ -1,3 +1,5 @@
1
+ from collections import defaultdict
2
+
1
3
  import logging
2
4
  import os
3
5
  import pathlib
@@ -5,10 +7,8 @@ import pickle
5
7
  import re
6
8
  import sqlite3
7
9
  import subprocess
8
- from collections import defaultdict
9
- from typing import Optional
10
-
11
10
  from junitparser.xunit2 import JUnitXml
11
+ from typing import Optional
12
12
 
13
13
  from codeflash.code_utils.code_utils import (
14
14
  module_name_from_file_path,
@@ -258,6 +258,7 @@ def merge_test_results(xml_test_results: TestResults, bin_test_results: TestResu
258
258
  )
259
259
  )
260
260
  else:
261
+ # Looks like we would never reach this condition because we are not printing the log line in the xml file
261
262
  for xml_result in xml_results:
262
263
  bin_result = bin_results.get_by_id(xml_result.id)
263
264
  if bin_result is None:
@@ -1,3 +1,3 @@
1
1
  # These version placeholders will be replaced by poetry-dynamic-versioning during `poetry build`.
2
- __version__ = "0.3.3"
3
- __version_tuple__ = (0, 3, 3)
2
+ __version__ = "0.3.4"
3
+ __version_tuple__ = (0, 3, 4)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "codeflash"
3
- version = "0.3.3" # Determined by poetry-dynamic-versioning during `poetry build`
3
+ version = "0.3.4" # Determined by poetry-dynamic-versioning during `poetry build`
4
4
  description = "A Code Performance Optimization Library"
5
5
  authors = ["CodeFlash Inc. <contact@codeflash.ai>"]
6
6
  homepage = "https://codeflash.ai"
@@ -22,7 +22,7 @@ pytest-timeout = ">=2.1.0"
22
22
  tomlkit = ">=0.11.7"
23
23
  unittest-xml-reporting = ">=3.2.0"
24
24
  junitparser = ">=3.1.0"
25
- pydantic = "^2.5.2"
25
+ pydantic = ">=1.10.1"
26
26
  black = ">=22.3.0"
27
27
  humanize = ">=4.0.0"
28
28
  posthog = ">=3.0.0"
@@ -60,7 +60,7 @@ line-length = 100
60
60
  target-version = ['py312']
61
61
 
62
62
  [build-system]
63
- requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
63
+ requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.2.0,<2.0.0"]
64
64
  build-backend = "poetry_dynamic_versioning.backend"
65
65
 
66
66
  [tool.poetry.build]
File without changes
File without changes