Skip to content

Commit 004b6db

Browse files
committed
Use same versioning for monorepo
1 parent aabcdaa commit 004b6db

2 files changed

Lines changed: 36 additions & 37 deletions

File tree

  • libraries/microsoft-agents-a365-observability-extensions-semantickernel
  • versioning/helper

libraries/microsoft-agents-a365-observability-extensions-semantickernel/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
version=package_version,
2424
install_requires=get_dynamic_dependencies(
2525
use_compatible_release=False, # No upper bound
26-
use_exact_match=False, # Not exact match
26+
use_exact_match=False, # Not exact match
2727
),
2828
)

versioning/helper/setup_utils.py

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
def 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:
6768
def 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

Comments
 (0)