Apache Airflow provider package for Windows Remote Management (WinRM) protocol integration enabling remote command execution on Windows systems
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Utility functions to detect the current Airflow version and determine feature availability.
def get_base_airflow_version_tuple() -> tuple[int, int, int]:
"""
Get the base Airflow version as a tuple of integers.
Extracts major, minor, and micro version numbers from the current
Airflow installation, ignoring pre-release suffixes.
Returns:
tuple: (major, minor, micro) version numbers
Example:
For Airflow 2.10.1rc1, returns (2, 10, 1)
For Airflow 3.0.0, returns (3, 0, 0)
"""Usage Example:
from airflow.providers.microsoft.winrm.version_compat import get_base_airflow_version_tuple
version = get_base_airflow_version_tuple()
print(f"Running Airflow {version[0]}.{version[1]}.{version[2]}")
if version >= (3, 0, 0):
print("Using Airflow 3.0+ features")
elif version >= (2, 10, 0):
print("Using Airflow 2.10+ features")Boolean constants indicating Airflow version capabilities for conditional feature usage.
AIRFLOW_V_3_0_PLUS: bool
"""True if running Airflow 3.0.0 or later, False otherwise."""
AIRFLOW_V_3_1_PLUS: bool
"""True if running Airflow 3.1.0 or later, False otherwise."""Usage Examples:
from airflow.providers.microsoft.winrm.version_compat import AIRFLOW_V_3_0_PLUS, AIRFLOW_V_3_1_PLUS
# Conditional feature usage
if AIRFLOW_V_3_0_PLUS:
# Use Airflow 3.0+ specific features
print("Using enhanced task execution features")
else:
# Fallback for Airflow 2.x
print("Using legacy task execution")
# Version-specific imports
if AIRFLOW_V_3_1_PLUS:
from airflow.sdk.execution import TaskExecutionContext
else:
from airflow.models import TaskInstance as TaskExecutionContextVersion-aware imports providing consistent access to fundamental Airflow base classes across different versions.
BaseOperator: type
"""
Base operator class for creating Airflow tasks.
- Airflow 3.0+: Imported from airflow.sdk.BaseOperator
- Airflow 2.x: Imported from airflow.models.BaseOperator
"""
BaseHook: type
"""
Base hook class for creating Airflow connections.
- Airflow 3.1+: Imported from airflow.sdk.BaseHook
- Airflow 2.x/3.0: Imported from airflow.hooks.base.BaseHook
"""Usage Examples:
from airflow.providers.microsoft.winrm.version_compat import BaseHook, BaseOperator
# Create custom hook extending BaseHook
class CustomWinRMHook(BaseHook):
def __init__(self, connection_id: str):
super().__init__()
self.connection_id = connection_id
def get_conn(self):
# Implementation here
pass
# Create custom operator extending BaseOperator
class CustomWinRMOperator(BaseOperator):
def __init__(self, custom_param: str, **kwargs):
super().__init__(**kwargs)
self.custom_param = custom_param
def execute(self, context):
# Implementation here
passGet provider metadata and configuration details.
def get_provider_info() -> dict:
"""
Get provider information including version, dependencies, and configuration.
Returns:
dict: Provider metadata including name, version, description,
connection types, and hook/operator class names
"""Complete list of exported symbols for version compatibility module.
__all__ = [
"AIRFLOW_V_3_0_PLUS",
"AIRFLOW_V_3_1_PLUS",
"BaseOperator",
"BaseHook",
]Key Changes:
BaseOperator moved from airflow.models to airflow.sdkCode Compatibility:
# This works across versions
from airflow.providers.microsoft.winrm.version_compat import BaseOperator
class MyOperator(BaseOperator):
def execute(self, context):
# Context handling works across versions
task_instance = context['task_instance']
return "success"Key Changes:
BaseHook moved from airflow.hooks.base to airflow.sdkCode Compatibility:
# This works across versions
from airflow.providers.microsoft.winrm.version_compat import BaseHook
class MyHook(BaseHook):
def get_conn(self):
# Connection handling works across versions
conn = self.get_connection(self.conn_id)
return create_connection(conn)The module uses packaging.version for robust version parsing:
from packaging.version import Version
from airflow import __version__
airflow_version = Version(__version__)
major, minor, micro = airflow_version.major, airflow_version.minor, airflow_version.microThe module employs conditional imports based on detected version:
# For BaseOperator
if AIRFLOW_V_3_0_PLUS:
from airflow.sdk import BaseOperator
else:
from airflow.models import BaseOperator
# For BaseHook
if AIRFLOW_V_3_1_PLUS:
from airflow.sdk import BaseHook
else:
from airflow.hooks.base import BaseHookThe provider package is tested against multiple Airflow versions:
The main package __init__.py enforces minimum version requirements:
if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse("2.10.0"):
raise RuntimeError(
f"The package `apache-airflow-providers-microsoft-winrm:{__version__}` needs Apache Airflow 2.10.0+"
)If version detection fails, the module falls back to legacy imports with appropriate error messages for unsupported versions.
from airflow.providers.microsoft.winrm.version_compat import BaseHook, AIRFLOW_V_3_1_PLUS
class AdvancedWinRMHook(BaseHook):
def __init__(self, conn_id: str):
super().__init__()
self.conn_id = conn_id
def get_conn(self):
if AIRFLOW_V_3_1_PLUS:
# Use enhanced connection features
conn = self.get_connection(self.conn_id, include_secrets=True)
else:
# Use standard connection
conn = self.get_connection(self.conn_id)
return self._create_winrm_connection(conn)This approach ensures your custom extensions work seamlessly across all supported Airflow versions.
Install with Tessl CLI
npx tessl i tessl/pypi-apache-airflow-providers-microsoft-winrm