diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..d9cc428 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,121 @@ +# FEATURE MANAGEMENT FOR PYTHON - COPILOT INSTRUCTIONS + +--- + +## CORE PRINCIPLES + +### RULE 1: DO NOT REPEAT INSTRUCTIONS +**NEVER repeat instructions when guiding users. Users should follow instructions independently.** + +### RULE 2: REFERENCE OFFICIAL DOCUMENTATION +**ALWAYS** reference the [Azure SDK Python Design Guidelines](https://azure.github.io/azure-sdk/python_design.html) +- Link to specific pages when answering guidelines questions +- Use this as the authoritative source for SDK development guidance + +### RULE 3: VERIFY ENVIRONMENT FIRST +**REQUIRED CONDITIONS:** +- Always activate the Python virtual environment before running Python commands: + - On Windows: `.venv\Scripts\activate` + - On Linux/macOS: `source .venv/bin/activate` +- Use `python -m pip` instead of bare `pip` when installing packages. + +--- + +## DEV SETUP + +Install all dependencies with: + +```bash +python -m pip install -e ".[dev,test]" +``` + +This project requires **Python 3.10 or newer**. + +--- + +## PROJECT STRUCTURE + +- `featuremanagement/` — Synchronous feature management code +- `featuremanagement/aio/` — Async equivalents of feature management classes +- `featuremanagement/_models/` — Data models (feature flags, variants, telemetry) +- `featuremanagement/_time_window_filter/` — Time window filter with recurrence support +- `featuremanagement/azuremonitor/` — Optional Azure Monitor telemetry integration +- `tests/` — Unit tests (sync and async) +- `samples/` — Sample applications + +--- + +## CODE CONVENTIONS + +- All source files must include the Microsoft copyright header. +- All modules must have a module-level docstring. +- Maximum line length is 120 characters. +- Use type annotations on all functions and methods. + +--- + +## PYLINT OPERATIONS + +### RUNNING PYLINT + +**COMMAND:** +```bash +pylint featuremanagement +``` + +### FIXING PYLINT WARNINGS + +**ALLOWED ACTIONS:** +- ✅ Fix warnings with 100% confidence +- ✅ Use existing files for all solutions +- ✅ Reference official guidelines + +**FORBIDDEN ACTIONS:** +- ❌ Fix warnings without complete confidence +- ❌ Create new files for solutions +- ❌ Import non-existent modules +- ❌ Add new dependencies/imports +- ❌ Make unnecessary large changes +- ❌ Change code style without reason +- ❌ Delete code without clear justification + +--- + +## MYPY OPERATIONS + +### RUNNING MYPY + +**COMMAND:** +```bash +mypy featuremanagement +``` + +The project uses `strict = True` in `mypy.ini`. + +--- + +## CODE FORMATTING + +### RUNNING BLACK + +**COMMAND:** +```bash +black featuremanagement +``` + +Line length is configured to 120 in `pyproject.toml`. + +--- + +## TESTING + +### RUNNING TESTS + +**COMMAND:** +```bash +pytest tests +``` + +- Sync tests are in `tests/test_*.py` +- Async tests use `pytest-asyncio` and are in files ending with `_async.py` +- Run tests with: `pytest tests` diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 730bc75..49d6d81 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -17,8 +17,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r dev_requirements.txt - pip install . + python -m pip install ".[dev]" - name: Analysing the code with pylint run: | pylint featuremanagement @@ -30,9 +29,9 @@ jobs: uses: streetsidesoftware/cspell-action@v6.8.0 - name: Test with pytest run: | - pip install -r tests/requirements.txt + python -m pip install ".[test]" pytest tests --doctest-modules --cov-report=xml --cov-report=html - name: Analysing the samples with pylint run: | - pip install -r samples/requirements.txt + python -m pip install -r samples/requirements.txt pylint --disable=missing-function-docstring,missing-class-docstring samples tests \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index bfa9241..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -recursive-include tests *.py -include *.md -include LICENSE -include featuremanagement/*.py -include featuremanagement/aio/*.py -recursive-include samples *.py *.json diff --git a/cspell.config.yaml b/cspell.config.yaml index 7d80bb8..5777535 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -12,7 +12,7 @@ ignorePaths: - '.*' - 'build' - 'docs' - - 'dev_requirements.txt' + - 'node_modules' - '*.egg-info' - '*.ini' - '*.toml' diff --git a/dev_requirements.txt b/dev_requirements.txt deleted file mode 100644 index 1411462..0000000 --- a/dev_requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -pytest < 9.0.0 -pytest-cov < 8.0.0 -pytest-asyncio < 2.0.0 -black < 27.0.0 -pylint < 5.0.0 -mypy < 2.0.0 -sphinx < 9.0.0 -sphinx_rtd_theme < 4.0.0 -sphinx-toolbox < 5.0.0 -myst_parser < 5.0.0 -opentelemetry-api < 2.0.0 -opentelemetry-sdk < 2.0.0 diff --git a/featuremanagement/__init__.py b/featuremanagement/__init__.py index 0a06a1c..2e0dbb2 100644 --- a/featuremanagement/__init__.py +++ b/featuremanagement/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Feature management library for Python.""" + from ._featuremanager import FeatureManager from ._featurefilters import FeatureFilter from ._defaultfilters import TimeWindowFilter, TargetingFilter diff --git a/featuremanagement/_defaultfilters.py b/featuremanagement/_defaultfilters.py index 75b8b7a..d36ddc6 100644 --- a/featuremanagement/_defaultfilters.py +++ b/featuremanagement/_defaultfilters.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Built-in feature filter implementations.""" + import logging import hashlib from datetime import datetime, timezone diff --git a/featuremanagement/_featurefilters.py b/featuremanagement/_featurefilters.py index c8a5021..c8b1b39 100644 --- a/featuremanagement/_featurefilters.py +++ b/featuremanagement/_featurefilters.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Base class for feature filters.""" + from abc import ABC, abstractmethod from typing import Mapping, Callable, Any, Optional diff --git a/featuremanagement/_featuremanager.py b/featuremanagement/_featuremanager.py index 49a4cf6..4d829a5 100644 --- a/featuremanagement/_featuremanager.py +++ b/featuremanagement/_featuremanager.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Synchronous feature manager implementation.""" + import logging from typing import cast, overload, Any, Optional, Dict, Mapping, List, Tuple from ._defaultfilters import TimeWindowFilter, TargetingFilter diff --git a/featuremanagement/_featuremanagerbase.py b/featuremanagement/_featuremanagerbase.py index d79021f..fac7f34 100644 --- a/featuremanagement/_featuremanagerbase.py +++ b/featuremanagement/_featuremanagerbase.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Base class for feature manager implementations.""" + import hashlib import logging from abc import ABC diff --git a/featuremanagement/_models/__init__.py b/featuremanagement/_models/__init__.py index ef38d49..58f9403 100644 --- a/featuremanagement/_models/__init__.py +++ b/featuremanagement/_models/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Data models for feature management.""" + from ._feature_flag import FeatureFlag from ._variant import Variant from ._evaluation_event import EvaluationEvent diff --git a/featuremanagement/_models/_allocation.py b/featuremanagement/_models/_allocation.py index 09dba6a..dbdc4a4 100644 --- a/featuremanagement/_models/_allocation.py +++ b/featuremanagement/_models/_allocation.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Allocation model for feature variant assignment.""" + from typing import cast, List, Optional, Mapping, Dict, Any, Union from dataclasses import dataclass from ._constants import DEFAULT_WHEN_ENABLED, DEFAULT_WHEN_DISABLED, USER, GROUP, PERCENTILE, SEED diff --git a/featuremanagement/_models/_constants.py b/featuremanagement/_models/_constants.py index dd5ea35..a67e1d3 100644 --- a/featuremanagement/_models/_constants.py +++ b/featuremanagement/_models/_constants.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Constants used by feature management models.""" # Feature Flag FEATURE_FLAG_ID = "id" diff --git a/featuremanagement/_models/_evaluation_event.py b/featuremanagement/_models/_evaluation_event.py index c0d7827..1b69b11 100644 --- a/featuremanagement/_models/_evaluation_event.py +++ b/featuremanagement/_models/_evaluation_event.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Evaluation event model for feature flag telemetry.""" + from dataclasses import dataclass from typing import Optional from ._feature_flag import FeatureFlag diff --git a/featuremanagement/_models/_feature_conditions.py b/featuremanagement/_models/_feature_conditions.py index 2d2c276..e60c5e6 100644 --- a/featuremanagement/_models/_feature_conditions.py +++ b/featuremanagement/_models/_feature_conditions.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Feature flag condition models.""" + from collections.abc import Mapping from typing import Any, Dict, List from ._constants import ( diff --git a/featuremanagement/_models/_feature_flag.py b/featuremanagement/_models/_feature_flag.py index e0665c1..0ce9eed 100644 --- a/featuremanagement/_models/_feature_flag.py +++ b/featuremanagement/_models/_feature_flag.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Feature flag model.""" + from typing import cast, List, Union, Optional, Mapping, Any from ._feature_conditions import FeatureConditions from ._allocation import Allocation diff --git a/featuremanagement/_models/_targeting_context.py b/featuremanagement/_models/_targeting_context.py index 8aa1cba..7f9ee19 100644 --- a/featuremanagement/_models/_targeting_context.py +++ b/featuremanagement/_models/_targeting_context.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Targeting context model for user and group targeting.""" from typing import NamedTuple, List diff --git a/featuremanagement/_models/_telemetry.py b/featuremanagement/_models/_telemetry.py index c54ad84..c5387e7 100644 --- a/featuremanagement/_models/_telemetry.py +++ b/featuremanagement/_models/_telemetry.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Telemetry metadata model.""" + from typing import Dict from dataclasses import dataclass, field diff --git a/featuremanagement/_models/_variant.py b/featuremanagement/_models/_variant.py index 382ada3..da8695c 100644 --- a/featuremanagement/_models/_variant.py +++ b/featuremanagement/_models/_variant.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Variant model representing a feature flag variant.""" + from typing import Any diff --git a/featuremanagement/_models/_variant_assignment_reason.py b/featuremanagement/_models/_variant_assignment_reason.py index 5e8c2c7..773c1cb 100644 --- a/featuremanagement/_models/_variant_assignment_reason.py +++ b/featuremanagement/_models/_variant_assignment_reason.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Enum for variant assignment reasons.""" + from enum import Enum diff --git a/featuremanagement/_models/_variant_reference.py b/featuremanagement/_models/_variant_reference.py index 893c09e..2c671fb 100644 --- a/featuremanagement/_models/_variant_reference.py +++ b/featuremanagement/_models/_variant_reference.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Variant reference model.""" + from dataclasses import dataclass from typing import Optional, Mapping, Any from ._constants import VARIANT_REFERENCE_NAME, CONFIGURATION_VALUE, STATUS_OVERRIDE diff --git a/featuremanagement/_time_window_filter/__init__.py b/featuremanagement/_time_window_filter/__init__.py index 34290bd..fb9263b 100644 --- a/featuremanagement/_time_window_filter/__init__.py +++ b/featuremanagement/_time_window_filter/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Time window filter with recurrence support.""" + from ._recurrence_evaluator import is_match from ._models import Recurrence, TimeWindowFilterSettings diff --git a/featuremanagement/_time_window_filter/_models.py b/featuremanagement/_time_window_filter/_models.py index ff3574b..b7ec442 100644 --- a/featuremanagement/_time_window_filter/_models.py +++ b/featuremanagement/_time_window_filter/_models.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Data models for the time window filter.""" + from enum import Enum from typing import Dict, Any, Optional, List from datetime import datetime diff --git a/featuremanagement/_time_window_filter/_recurrence_evaluator.py b/featuremanagement/_time_window_filter/_recurrence_evaluator.py index 9034b89..7e7a8cb 100644 --- a/featuremanagement/_time_window_filter/_recurrence_evaluator.py +++ b/featuremanagement/_time_window_filter/_recurrence_evaluator.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Recurrence evaluation logic for the time window filter.""" + from datetime import datetime, timedelta from typing import Optional from ._models import RecurrencePatternType, RecurrenceRangeType, TimeWindowFilterSettings, OccurrenceInfo, Recurrence diff --git a/featuremanagement/_time_window_filter/_recurrence_validator.py b/featuremanagement/_time_window_filter/_recurrence_validator.py index 8c34aaa..160e026 100644 --- a/featuremanagement/_time_window_filter/_recurrence_validator.py +++ b/featuremanagement/_time_window_filter/_recurrence_validator.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Validation logic for recurrence settings.""" + from datetime import datetime, timedelta from typing import List from ._models import RecurrencePatternType, RecurrenceRangeType, Recurrence, RecurrencePattern, RecurrenceRange diff --git a/featuremanagement/_version.py b/featuremanagement/_version.py index bade305..61b4d08 100644 --- a/featuremanagement/_version.py +++ b/featuremanagement/_version.py @@ -3,5 +3,6 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Package version.""" VERSION = "2.1.0" diff --git a/featuremanagement/aio/__init__.py b/featuremanagement/aio/__init__.py index 34c5471..ff46abb 100644 --- a/featuremanagement/aio/__init__.py +++ b/featuremanagement/aio/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Async feature management support.""" + from ._featuremanager import FeatureManager from ._featurefilters import FeatureFilter from ._defaultfilters import TimeWindowFilter, TargetingFilter diff --git a/featuremanagement/aio/_defaultfilters.py b/featuremanagement/aio/_defaultfilters.py index ab8c1d8..e6b2d68 100644 --- a/featuremanagement/aio/_defaultfilters.py +++ b/featuremanagement/aio/_defaultfilters.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Built-in async feature filter implementations.""" + from typing import Mapping, Any from ._featurefilters import FeatureFilter from .._defaultfilters import ( diff --git a/featuremanagement/aio/_featurefilters.py b/featuremanagement/aio/_featurefilters.py index 5305eaf..627e1ed 100644 --- a/featuremanagement/aio/_featurefilters.py +++ b/featuremanagement/aio/_featurefilters.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Base class for async feature filters.""" + from abc import ABC, abstractmethod from typing import Mapping, Callable, Any, Optional diff --git a/featuremanagement/aio/_featuremanager.py b/featuremanagement/aio/_featuremanager.py index d5f45a7..4a7b475 100644 --- a/featuremanagement/aio/_featuremanager.py +++ b/featuremanagement/aio/_featuremanager.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Async feature manager implementation.""" + import inspect import logging from typing import cast, overload, Any, Optional, Dict, Mapping, List, Tuple diff --git a/featuremanagement/azuremonitor/__init__.py b/featuremanagement/azuremonitor/__init__.py index 135fdf7..b09ac6f 100644 --- a/featuremanagement/azuremonitor/__init__.py +++ b/featuremanagement/azuremonitor/__init__.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Azure Monitor telemetry integration for feature management.""" + from ._send_telemetry import publish_telemetry, track_event, TargetingSpanProcessor __all__ = [ diff --git a/featuremanagement/azuremonitor/_send_telemetry.py b/featuremanagement/azuremonitor/_send_telemetry.py index 0a7f727..48c33d3 100644 --- a/featuremanagement/azuremonitor/_send_telemetry.py +++ b/featuremanagement/azuremonitor/_send_telemetry.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Telemetry publishing for feature evaluation events.""" + import logging import inspect from typing import Any, Callable, Dict, Optional diff --git a/mypy.ini b/mypy.ini index 0a01c74..f24c551 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,31 +1,4 @@ [mypy] python_version = 3.10 -# Start off with these -warn_unused_configs = True -warn_redundant_casts = True -warn_unused_ignores = True - -# Getting these passing should be easy -strict_equality = True -extra_checks = True - -# Strongly recommend enabling this one as soon as you can -check_untyped_defs = True - -# These shouldn't be too much additional work, but may be tricky to -# get passing if you use a lot of untyped libraries -disallow_subclassing_any = True -disallow_untyped_decorators = True -disallow_any_generics = True - -# These next few are various gradations of forcing use of type annotations -disallow_untyped_calls = True -disallow_incomplete_defs = True -disallow_untyped_defs = True - -# This one isn't too hard to get passing, but return on investment is lower -no_implicit_reexport = True - -# This one can be tricky to get passing if you use a lot of untyped libraries -warn_return_any = True +strict = True diff --git a/pyproject.toml b/pyproject.toml index d160c35..da3aa6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,20 +6,24 @@ pythonpath = [ [tool.black] line-length = 120 -[tool.pylint] +[tool.pylint.format] max-line-length = 120 + +[tool.pylint.design] min-public-methods = 1 max-branches = 20 max-returns = 7 -disable = ["missing-module-docstring", "duplicate-code"] + +[tool.pylint."messages_control"] +disable = ["duplicate-code"] [build-system] -requires = ["setuptools>=61.0", "pylint", "pytest-asyncio", "mypy", "black"] +requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "FeatureManagement" -version = "2.1.0" +dynamic = ["version"] authors = [ { name="Microsoft Corporation", email="appconfig@microsoft.com" }, ] @@ -40,9 +44,36 @@ classifiers = [ "License :: OSI Approved :: MIT License", ] +[tool.setuptools.dynamic] +version = {attr = "featuremanagement._version.VERSION"} + +[tool.setuptools.packages.find] +include = ["featuremanagement*"] + +[tool.setuptools.package-data] +featuremanagement = ["py.typed"] + [project.urls] Homepage = "https://github.com/microsoft/FeatureManagement-Python" Issues = "https://github.com/microsoft/FeatureManagement-Python/issues" [project.optional-dependencies] AzureMonitor = ["azure-monitor-events-extension<2.0.0"] +test = [ + "azure-monitor-opentelemetry < 2.0.0", + "azure-monitor-events-extension < 2.0.0", +] +dev = [ + "pytest >= 7.0.0, < 10.0.0", + "pytest-cov >= 4.0.0, < 8.0.0", + "pytest-asyncio >= 0.21.0, < 2.0.0", + "black >= 23.0.0, < 27.0.0", + "pylint >= 3.0.0, < 5.0.0", + "mypy >= 1.0.0, < 2.0.0", + "sphinx >= 7.0.0, < 10.0.0", + "sphinx_rtd_theme >= 2.0.0, < 4.0.0", + "sphinx-toolbox >= 3.0.0, < 5.0.0", + "myst_parser >= 2.0.0, < 6.0.0", + "opentelemetry-api >= 1.20.0, < 2.0.0", + "opentelemetry-sdk >= 1.20.0, < 2.0.0", +] diff --git a/samples/feature_flag_sample.py b/samples/feature_flag_sample.py index f3aa59b..ad8c011 100644 --- a/samples/feature_flag_sample.py +++ b/samples/feature_flag_sample.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Sample demonstrating basic feature flag usage.""" import json import os diff --git a/samples/feature_flag_with_azure_app_configuration_sample.py b/samples/feature_flag_with_azure_app_configuration_sample.py index dedf3bd..13a3e35 100644 --- a/samples/feature_flag_with_azure_app_configuration_sample.py +++ b/samples/feature_flag_with_azure_app_configuration_sample.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Sample demonstrating feature flags with Azure App Configuration.""" from time import sleep import os diff --git a/samples/feature_variant_sample.py b/samples/feature_variant_sample.py index fb96308..1dac737 100644 --- a/samples/feature_variant_sample.py +++ b/samples/feature_variant_sample.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Sample demonstrating feature variants.""" import json import os diff --git a/samples/feature_variant_sample_with_targeting_accessor.py b/samples/feature_variant_sample_with_targeting_accessor.py index 887a01b..e416d27 100644 --- a/samples/feature_variant_sample_with_targeting_accessor.py +++ b/samples/feature_variant_sample_with_targeting_accessor.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Sample demonstrating feature variants with a targeting accessor.""" import json import os diff --git a/samples/feature_variant_sample_with_telemetry.py b/samples/feature_variant_sample_with_telemetry.py index 72991b8..915a034 100644 --- a/samples/feature_variant_sample_with_telemetry.py +++ b/samples/feature_variant_sample_with_telemetry.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Sample demonstrating feature variants with telemetry.""" + import json import os import sys diff --git a/samples/quarty_sample.py b/samples/quarty_sample.py index 8bfd08e..211e065 100644 --- a/samples/quarty_sample.py +++ b/samples/quarty_sample.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Sample demonstrating Quart web app with feature management.""" import uuid import os diff --git a/samples/random_filter.py b/samples/random_filter.py index 86084ae..1ee756f 100644 --- a/samples/random_filter.py +++ b/samples/random_filter.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +"""Sample custom feature filter using random evaluation.""" + import random from featuremanagement import FeatureFilter diff --git a/setup.py b/setup.py deleted file mode 100644 index 5863ab5..0000000 --- a/setup.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python - -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- - -import re -import os.path -from io import open -from setuptools import find_packages, setup - -# Change the PACKAGE_NAME only to change folder and different name -PACKAGE_NAME = "featuremanagement" -PACKAGE_PPRINT_NAME = "Feature Management" - -# a-b-c => a/b/c -package_folder_path = PACKAGE_NAME.replace("-", "/") -# a-b-c => a.b.c -namespace_name = PACKAGE_NAME.replace("-", ".") - -# Version extraction inspired from 'requests' -with open(os.path.join(package_folder_path, "_version.py"), "r") as fd: - version = re.search(r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE).group(1) - -if not version: - raise RuntimeError("Cannot find version information") - -with open("README.md", encoding="utf-8") as f: - readme = f.read() -with open("CHANGELOG.md", encoding="utf-8") as f: - changelog = f.read() - -setup( - name=PACKAGE_NAME, - version=version, - include_package_data=True, - description="Microsoft {} Library for Python".format(PACKAGE_PPRINT_NAME), - long_description=readme + "\n\n" + changelog, - long_description_content_type="text/markdown", - author="Microsoft Corporation", - author_email="appconfig@microsoft.com", - url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/feature-management", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Programming Language :: Python", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - "License :: OSI Approved :: MIT License", - ], - zip_safe=False, - packages=find_packages(), - python_requires=">=3.10", - install_requires=[], - extras_require={ - "AzureMonitor": ["azure-monitor-events-extension<2.0.0"], - }, -) diff --git a/tests/requirements.txt b/tests/requirements.txt deleted file mode 100644 index f52da80..0000000 --- a/tests/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -azure-monitor-opentelemetry -azure-monitor-events-extension \ No newline at end of file diff --git a/tests/test_default_feature_flags.py b/tests/test_default_feature_flags.py index 7e4345a..b9c0dd1 100644 --- a/tests/test_default_feature_flags.py +++ b/tests/test_default_feature_flags.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for built-in feature filters.""" + import unittest import pytest from featuremanagement import FeatureManager, TargetingContext diff --git a/tests/test_default_feature_flags_async.py b/tests/test_default_feature_flags_async.py index c8d2048..77eed66 100644 --- a/tests/test_default_feature_flags_async.py +++ b/tests/test_default_feature_flags_async.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Async tests for built-in feature filters.""" + from unittest import IsolatedAsyncioTestCase import pytest from featuremanagement.aio import FeatureManager diff --git a/tests/test_feature_manager.py b/tests/test_feature_manager.py index 7813835..b9a0fc6 100644 --- a/tests/test_feature_manager.py +++ b/tests/test_feature_manager.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for the synchronous FeatureManager.""" + import unittest import pytest from featuremanagement import FeatureManager, FeatureFilter diff --git a/tests/test_feature_manager_async.py b/tests/test_feature_manager_async.py index 1f6c959..d224ba9 100644 --- a/tests/test_feature_manager_async.py +++ b/tests/test_feature_manager_async.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for the async FeatureManager.""" + import unittest import pytest from featuremanagement.aio import FeatureManager, FeatureFilter diff --git a/tests/test_feature_manager_refresh.py b/tests/test_feature_manager_refresh.py index 39e23b2..148f2cb 100644 --- a/tests/test_feature_manager_refresh.py +++ b/tests/test_feature_manager_refresh.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for feature manager configuration refresh.""" + import pytest from featuremanagement import FeatureManager from featuremanagement.aio import FeatureManager as AsyncFeatureManager diff --git a/tests/test_feature_variants.py b/tests/test_feature_variants.py index 860d70b..01e6959 100644 --- a/tests/test_feature_variants.py +++ b/tests/test_feature_variants.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for feature variant assignment.""" + import unittest from featuremanagement import FeatureManager, FeatureFilter, TargetingContext diff --git a/tests/test_feature_variants_async.py b/tests/test_feature_variants_async.py index 9b4a71c..505a0e0 100644 --- a/tests/test_feature_variants_async.py +++ b/tests/test_feature_variants_async.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Async tests for feature variant assignment.""" + from unittest import IsolatedAsyncioTestCase from featuremanagement.aio import FeatureManager, FeatureFilter from featuremanagement import TargetingContext diff --git a/tests/test_send_telemetry_appinsights.py b/tests/test_send_telemetry_appinsights.py index 52eab4e..4922070 100644 --- a/tests/test_send_telemetry_appinsights.py +++ b/tests/test_send_telemetry_appinsights.py @@ -3,6 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +"""Tests for Application Insights telemetry publishing.""" + import logging from unittest.mock import patch import pytest