or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdversion-compatibility.mdwinrm-hook.mdwinrm-operator.md

version-compatibility.mddocs/

0

# Version Compatibility

1

2

Cross-version compatibility utilities ensuring seamless operation across different Apache Airflow versions. Provides version detection and consistent access to base classes while maintaining backward compatibility.

3

4

## Capabilities

5

6

### Version Detection

7

8

Utility functions to detect the current Airflow version and determine feature availability.

9

10

```python { .api }

11

def get_base_airflow_version_tuple() -> tuple[int, int, int]:

12

"""

13

Get the base Airflow version as a tuple of integers.

14

15

Extracts major, minor, and micro version numbers from the current

16

Airflow installation, ignoring pre-release suffixes.

17

18

Returns:

19

tuple: (major, minor, micro) version numbers

20

21

Example:

22

For Airflow 2.10.1rc1, returns (2, 10, 1)

23

For Airflow 3.0.0, returns (3, 0, 0)

24

"""

25

```

26

27

**Usage Example:**

28

29

```python

30

from airflow.providers.microsoft.winrm.version_compat import get_base_airflow_version_tuple

31

32

version = get_base_airflow_version_tuple()

33

print(f"Running Airflow {version[0]}.{version[1]}.{version[2]}")

34

35

if version >= (3, 0, 0):

36

print("Using Airflow 3.0+ features")

37

elif version >= (2, 10, 0):

38

print("Using Airflow 2.10+ features")

39

```

40

41

### Version Flags

42

43

Boolean constants indicating Airflow version capabilities for conditional feature usage.

44

45

```python { .api }

46

AIRFLOW_V_3_0_PLUS: bool

47

"""True if running Airflow 3.0.0 or later, False otherwise."""

48

49

AIRFLOW_V_3_1_PLUS: bool

50

"""True if running Airflow 3.1.0 or later, False otherwise."""

51

```

52

53

**Usage Examples:**

54

55

```python

56

from airflow.providers.microsoft.winrm.version_compat import AIRFLOW_V_3_0_PLUS, AIRFLOW_V_3_1_PLUS

57

58

# Conditional feature usage

59

if AIRFLOW_V_3_0_PLUS:

60

# Use Airflow 3.0+ specific features

61

print("Using enhanced task execution features")

62

else:

63

# Fallback for Airflow 2.x

64

print("Using legacy task execution")

65

66

# Version-specific imports

67

if AIRFLOW_V_3_1_PLUS:

68

from airflow.sdk.execution import TaskExecutionContext

69

else:

70

from airflow.models import TaskInstance as TaskExecutionContext

71

```

72

73

### Base Class Compatibility

74

75

Version-aware imports providing consistent access to fundamental Airflow base classes across different versions.

76

77

```python { .api }

78

BaseOperator: type

79

"""

80

Base operator class for creating Airflow tasks.

81

- Airflow 3.0+: Imported from airflow.sdk.BaseOperator

82

- Airflow 2.x: Imported from airflow.models.BaseOperator

83

"""

84

85

BaseHook: type

86

"""

87

Base hook class for creating Airflow connections.

88

- Airflow 3.1+: Imported from airflow.sdk.BaseHook

89

- Airflow 2.x/3.0: Imported from airflow.hooks.base.BaseHook

90

"""

91

```

92

93

**Usage Examples:**

94

95

```python

96

from airflow.providers.microsoft.winrm.version_compat import BaseHook, BaseOperator

97

98

# Create custom hook extending BaseHook

99

class CustomWinRMHook(BaseHook):

100

def __init__(self, connection_id: str):

101

super().__init__()

102

self.connection_id = connection_id

103

104

def get_conn(self):

105

# Implementation here

106

pass

107

108

# Create custom operator extending BaseOperator

109

class CustomWinRMOperator(BaseOperator):

110

def __init__(self, custom_param: str, **kwargs):

111

super().__init__(**kwargs)

112

self.custom_param = custom_param

113

114

def execute(self, context):

115

# Implementation here

116

pass

117

```

118

119

### Provider Information

120

121

Get provider metadata and configuration details.

122

123

```python { .api }

124

def get_provider_info() -> dict:

125

"""

126

Get provider information including version, dependencies, and configuration.

127

128

Returns:

129

dict: Provider metadata including name, version, description,

130

connection types, and hook/operator class names

131

"""

132

```

133

134

### Package Exports

135

136

Complete list of exported symbols for version compatibility module.

137

138

```python { .api }

139

__all__ = [

140

"AIRFLOW_V_3_0_PLUS",

141

"AIRFLOW_V_3_1_PLUS",

142

"BaseOperator",

143

"BaseHook",

144

]

145

```

146

147

## Version Migration Guide

148

149

### Airflow 2.10 to 3.0 Migration

150

151

**Key Changes:**

152

- `BaseOperator` moved from `airflow.models` to `airflow.sdk`

153

- Task execution context changes

154

- Enhanced task lifecycle management

155

156

**Code Compatibility:**

157

```python

158

# This works across versions

159

from airflow.providers.microsoft.winrm.version_compat import BaseOperator

160

161

class MyOperator(BaseOperator):

162

def execute(self, context):

163

# Context handling works across versions

164

task_instance = context['task_instance']

165

return "success"

166

```

167

168

### Airflow 3.0 to 3.1 Migration

169

170

**Key Changes:**

171

- `BaseHook` moved from `airflow.hooks.base` to `airflow.sdk`

172

- Enhanced connection management

173

- Improved hook lifecycle

174

175

**Code Compatibility:**

176

```python

177

# This works across versions

178

from airflow.providers.microsoft.winrm.version_compat import BaseHook

179

180

class MyHook(BaseHook):

181

def get_conn(self):

182

# Connection handling works across versions

183

conn = self.get_connection(self.conn_id)

184

return create_connection(conn)

185

```

186

187

## Implementation Details

188

189

### Version Detection Logic

190

191

The module uses `packaging.version` for robust version parsing:

192

193

```python

194

from packaging.version import Version

195

from airflow import __version__

196

197

airflow_version = Version(__version__)

198

major, minor, micro = airflow_version.major, airflow_version.minor, airflow_version.micro

199

```

200

201

### Import Strategy

202

203

The module employs conditional imports based on detected version:

204

205

```python

206

# For BaseOperator

207

if AIRFLOW_V_3_0_PLUS:

208

from airflow.sdk import BaseOperator

209

else:

210

from airflow.models import BaseOperator

211

212

# For BaseHook

213

if AIRFLOW_V_3_1_PLUS:

214

from airflow.sdk import BaseHook

215

else:

216

from airflow.hooks.base import BaseHook

217

```

218

219

### Compatibility Testing

220

221

The provider package is tested against multiple Airflow versions:

222

- Airflow 2.10.x (minimum supported)

223

- Airflow 3.0.x (major version transition)

224

- Airflow 3.1.x (latest features)

225

226

## Error Handling

227

228

### Version Requirement Enforcement

229

230

The main package `__init__.py` enforces minimum version requirements:

231

232

```python

233

if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse("2.10.0"):

234

raise RuntimeError(

235

f"The package `apache-airflow-providers-microsoft-winrm:{__version__}` needs Apache Airflow 2.10.0+"

236

)

237

```

238

239

### Import Failures

240

241

If version detection fails, the module falls back to legacy imports with appropriate error messages for unsupported versions.

242

243

## Best Practices

244

245

### Using Version Compatibility

246

247

1. **Always use version_compat imports** for base classes instead of direct imports

248

2. **Check version flags** before using version-specific features

249

3. **Test across supported versions** when extending the provider

250

4. **Handle version differences gracefully** in custom implementations

251

252

### Example: Version-Aware Custom Hook

253

254

```python

255

from airflow.providers.microsoft.winrm.version_compat import BaseHook, AIRFLOW_V_3_1_PLUS

256

257

class AdvancedWinRMHook(BaseHook):

258

def __init__(self, conn_id: str):

259

super().__init__()

260

self.conn_id = conn_id

261

262

def get_conn(self):

263

if AIRFLOW_V_3_1_PLUS:

264

# Use enhanced connection features

265

conn = self.get_connection(self.conn_id, include_secrets=True)

266

else:

267

# Use standard connection

268

conn = self.get_connection(self.conn_id)

269

270

return self._create_winrm_connection(conn)

271

```

272

273

This approach ensures your custom extensions work seamlessly across all supported Airflow versions.