Repository: kedro-org/kedro
File: kedro/framework/project/__init__.py (Python)

Code before:
class _ProjectLogging(UserDict):
    def __init__(self) -> None:
        """Initialise project logging. The path to logging configuration is given in
        environment variable KEDRO_LOGGING_CONFIG (defaults to conf/logging.yml)."""

        # Check if a user path is set in the environment variable
        user_logging_path = os.environ.get("KEDRO_LOGGING_CONFIG")

        # Check if the default logging configuration exists
        default_logging_path = Path("conf/logging.yml")
        if not default_logging_path.exists():
            default_logging_path = Path(__file__).parent / "default_logging.yml"

        # Use the user path if available, otherwise, use the default path
        if user_logging_path and Path(user_logging_path).exists():
            path = Path(user_logging_path)
        else:
            path = default_logging_path

        # Load and apply the logging configuration
        logging_config = Path(path).read_text(encoding="utf-8")
        self.configure(yaml.safe_load(logging_config))

        # Log info about the logging configuration
        if not user_logging_path and path.resolve() == (
            Path("conf/logging.yml").resolve()
        ):
            logger = logging.getLogger(__name__)
            logger.info(
                "Using `conf/logging.yml` as logging configuration. "
                "You can change this by setting the KEDRO_LOGGING_CONFIG environment variable accordingly."
            )

    def configure(self, logging_config: dict[str, Any]) -> None:
        """Configure project logging using ``logging_config`` (e.g. from project
        logging.yml). We store this in the UserDict data so that it can be reconfigured
        in _bootstrap_subprocess.
        """
        logging.config.dictConfig(logging_config)
        self.data = logging_config

    def set_project_logging(self, package_name: str) -> None:
        """Add the project level logging to the loggers upon provision of a package name.
        Checks if project logger already exists to prevent overwriting, if none exists
        it defaults to setting project logs at INFO level."""
        if package_name not in self.data["loggers"]:
            self.data["loggers"][package_name] = {"level": "INFO"}
            self.configure(self.data)


PACKAGE_NAME = None

Review comment (bug):
@SajidAlamQB I suspect the windows test is failing because on windows this path is not being resolved properly, it happens on GHA. try absolute path - `(project_path / Path("conf/logging.yml")).resolve()`

Code after:
class _ProjectLogging(UserDict):
    def __init__(self) -> None:
        """Initialise project logging. The path to logging configuration is given in
        environment variable KEDRO_LOGGING_CONFIG (defaults to conf/logging.yml)."""

        # Check if a user path is set in the environment variable
        user_logging_path = os.environ.get("KEDRO_LOGGING_CONFIG")

        # Check if the default logging configuration exists
        default_logging_path = Path("conf/logging.yml")
        if not default_logging_path.exists():
            default_logging_path = Path(__file__).parent / "default_logging.yml"

        # Use the user path if available, otherwise, use the default path
        if user_logging_path and Path(user_logging_path).exists():
            path = Path(user_logging_path)
        else:
            path = default_logging_path

        # Load and apply the logging configuration
        logging_config = Path(path).read_text(encoding="utf-8")
        self.configure(yaml.safe_load(logging_config))

        # Log info about the logging configuration
        if not user_logging_path and default_logging_path == Path("conf/logging.yml"):
            logger = logging.getLogger(__name__)
            logger.info(
                f"Using `{path}` as logging configuration. "
                f"You can change this by setting the KEDRO_LOGGING_CONFIG environment variable accordingly."
            )

    def configure(self, logging_config: dict[str, Any]) -> None:
        """Configure project logging using ``logging_config`` (e.g. from project
        logging.yml). We store this in the UserDict data so that it can be reconfigured
        in _bootstrap_subprocess.
        """
        logging.config.dictConfig(logging_config)
        self.data = logging_config

    def set_project_logging(self, package_name: str) -> None:
        """Add the project level logging to the loggers upon provision of a package name.
        Checks if project logger already exists to prevent overwriting, if none exists
        it defaults to setting project logs at INFO level."""
        if package_name not in self.data["loggers"]:
            self.data["loggers"][package_name] = {"level": "INFO"}
            self.configure(self.data)


PACKAGE_NAME = None
LOGGING = _ProjectLogging()