1515def get_package_version () -> str :
1616 """
1717 Get the package version from environment variable.
18-
18+
1919 Returns:
2020 The version string from AGENT365_PYTHON_SDK_PACKAGE_VERSION environment variable,
2121 or "0.0.0" if not set.
@@ -27,37 +27,38 @@ def get_base_version(version_string: str) -> str:
2727 """
2828 Extract the base version (major.minor.micro) from a version string,
2929 removing any dev, alpha, beta, rc, or post-release suffixes.
30-
30+
3131 Uses the packaging library for robust PEP 440 compliant parsing.
32-
32+
3333 Examples:
3434 "0.1.0.dev5" -> "0.1.0"
3535 "0.2.0" -> "0.2.0"
3636 "1.0.0a1" -> "1.0.0"
3737 "1.2.3b2" -> "1.2.3"
3838 "2.0.0rc1" -> "2.0.0"
3939 "1.a.3" -> "1.0.3" (handles edge cases correctly)
40-
40+
4141 Args:
4242 version_string: Version string to parse
43-
43+
4444 Returns:
4545 Base version string in format "major.minor.micro"
4646 """
4747 try :
4848 from packaging .version import Version
49-
49+
5050 # Parse the version using packaging library (PEP 440 compliant)
5151 parsed = Version (version_string )
52-
52+
5353 # Return base release version (major.minor.micro)
5454 return f"{ parsed .major } .{ parsed .minor } .{ parsed .micro } "
5555 except Exception :
5656 # Fallback to simple parsing if packaging fails or isn't available
5757 # Remove known suffixes (less robust but works for simple cases)
5858 import re
59+
5960 # Match version up to dev/alpha/beta/rc suffixes
60- match = re .match (r' ^(\d+\.\d+\.\d+)' , version_string )
61+ match = re .match (r" ^(\d+\.\d+\.\d+)" , version_string )
6162 if match :
6263 return match .group (1 )
6364 # Last resort: return as-is
@@ -67,21 +68,21 @@ def get_base_version(version_string: str) -> str:
6768def get_next_major_version (base_version : str ) -> str :
6869 """
6970 Calculate the next major version for upper bound in compatible release.
70-
71+
7172 For 0.x.y versions, increments minor (0.1.0 -> 0.2.0)
7273 For x.y.z versions where x > 0, increments major (1.2.3 -> 2.0.0)
73-
74+
7475 Args:
7576 base_version: Base version string (e.g., "0.1.0" or "1.2.3")
76-
77+
7778 Returns:
7879 Next major version string
7980 """
8081 try :
8182 from packaging .version import Version
82-
83+
8384 parsed = Version (base_version )
84-
85+
8586 if parsed .major == 0 :
8687 # For 0.x.y, increment minor version (0.1.0 -> 0.2.0)
8788 return f"{ parsed .major } .{ parsed .minor + 1 } .0"
@@ -108,43 +109,43 @@ def get_dynamic_dependencies(
108109) -> List [str ]:
109110 """
110111 Read dependencies from pyproject.toml and update internal package versions.
111-
112+
112113 Internal packages (microsoft-agents-a365-*) can use different versioning strategies:
113-
114+
114115 1. Minimum version (default, recommended):
115116 >= base_version
116117 Example: >= 0.1.0
117118 - Maximum flexibility for consumers
118-
119+
119120 2. Compatible release:
120121 >= base_version, < next_major_version
121122 Example: >= 0.1.0, < 0.2.0
122123 - Allows updates within major version
123-
124+
124125 3. Exact match:
125126 == current_version
126127 Example: == 0.1.0.dev5
127128 - Forces exact version match
128-
129+
129130 External packages keep their original version constraints.
130-
131+
131132 Args:
132133 pyproject_path: Path to the pyproject.toml file (default: "pyproject.toml")
133134 use_exact_match: If True, use == for internal packages
134135 use_compatible_release: If True, use >= with < upper bound
135-
136+
136137 Returns:
137138 List of dependency strings with updated internal package versions
138-
139+
139140 Raises:
140141 FileNotFoundError: If pyproject.toml doesn't exist
141142 ValueError: If pyproject.toml is invalid or missing required fields
142143 """
143144 package_version = get_package_version ()
144-
145+
145146 # Extract base version using robust parsing
146147 base_version = get_base_version (package_version )
147-
148+
148149 # Load TOML library (Python 3.11+ has built-in, older versions need tomli)
149150 try :
150151 import tomllib # Python 3.11+
@@ -156,7 +157,7 @@ def get_dynamic_dependencies(
156157 "Failed to import TOML library. For Python < 3.11, please install tomli: "
157158 "pip install tomli"
158159 )
159-
160+
160161 # Read and parse pyproject.toml with comprehensive error handling
161162 try :
162163 with open (pyproject_path , "rb" ) as f :
@@ -169,8 +170,7 @@ def get_dynamic_dependencies(
169170 )
170171 except PermissionError :
171172 raise PermissionError (
172- f"Permission denied reading { pyproject_path } . "
173- f"Check file permissions."
173+ f"Permission denied reading { pyproject_path } . Check file permissions."
174174 )
175175 except Exception as e :
176176 # Catch TOML decode errors (attribute may vary by library)
@@ -180,30 +180,29 @@ def get_dynamic_dependencies(
180180 f"Please check the file for syntax errors."
181181 )
182182 # Re-raise unexpected errors
183- raise RuntimeError (
184- f"Unexpected error reading { pyproject_path } : { type (e ).__name__ } : { e } "
185- )
186-
183+ raise RuntimeError (f"Unexpected error reading { pyproject_path } : { type (e ).__name__ } : { e } " )
184+
187185 # Validate pyproject.toml structure
188186 if "project" not in pyproject :
189187 raise ValueError (
190188 f"{ pyproject_path } is missing [project] section. "
191189 f"This is required for PEP 621 compliant packages."
192190 )
193-
191+
194192 dependencies = pyproject .get ("project" , {}).get ("dependencies" , [])
195-
193+
196194 # Warn if no dependencies found (might be intentional, so don't fail)
197195 if not dependencies :
198196 # Note: Using print instead of logging to avoid additional dependencies
199197 # In production, consider using logging module
200198 import sys
199+
201200 print (
202201 f"Warning: No dependencies found in { pyproject_path } . "
203202 f"This may be intentional for packages with no dependencies." ,
204203 file = sys .stderr ,
205204 )
206-
205+
207206 # Update internal package versions dynamically
208207 updated_dependencies = []
209208 for dep in dependencies :
@@ -214,11 +213,11 @@ def get_dynamic_dependencies(
214213 file = sys .stderr ,
215214 )
216215 continue
217-
216+
218217 if dep .startswith ("microsoft-agents-a365-" ):
219218 # Extract package name (everything before >=, ==, or other operators)
220219 pkg_name = dep .split (">=" )[0 ].split ("==" )[0 ].split ("<" )[0 ].strip ()
221-
220+
222221 if use_exact_match :
223222 # Exact match: == current_version
224223 updated_dependencies .append (f"{ pkg_name } == { package_version } " )
@@ -232,5 +231,5 @@ def get_dynamic_dependencies(
232231 else :
233232 # Keep external dependencies as-is
234233 updated_dependencies .append (dep )
235-
234+
236235 return updated_dependencies
0 commit comments