{
    "file_diffs": [
        {
            "old_file_content": "import asyncio\nimport calendar\nimport contextlib\nimport datetime\nimport heapq\nimport itertools\nimport os  # noqa\nimport pathlib\nimport pickle\nimport re\nimport time\nfrom collections import defaultdict\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import (\n    DefaultDict,\n    Dict,\n    Iterable,\n    Iterator,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Union,\n    cast,\n)\n\nfrom yarl import URL\n\nfrom .abc import AbstractCookieJar, ClearCookiePredicate\nfrom .helpers import is_ip_address\nfrom .typedefs import LooseCookies, PathLike, StrOrURL\n\n__all__ = (\"CookieJar\", \"DummyCookieJar\")\n\n\nCookieItem = Union[str, \"Morsel[str]\"]\n\n# We cache these string methods here as their use is in performance critical code.\n_FORMAT_PATH = \"{}/{}\".format\n_FORMAT_DOMAIN_REVERSED = \"{1}.{0}\".format\n\n# The minimum number of scheduled cookie expirations before we start cleaning up\n# the expiration heap. This is a performance optimization to avoid cleaning up the\n# heap too often when there are only a few scheduled expirations.\n_MIN_SCHEDULED_COOKIE_EXPIRATION = 100\n\n\nclass CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))\n\n\nclass DummyCookieJar(AbstractCookieJar):\n    \"\"\"Implements a dummy cookie storage.\n\n    It can be used with the ClientSession when no cookie processing is needed.\n\n    \"\"\"\n\n    def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:\n        super().__init__(loop=loop)\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        while False:\n            yield None\n\n    def __len__(self) -> int:\n        return 0\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        pass\n\n    def clear_domain(self, domain: str) -> None:\n        pass\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        pass\n\n    def filter_cookies(self, request_url: URL) -> \"BaseCookie[str]\":\n        return SimpleCookie()\n",
            "new_file_content": "import asyncio\nimport calendar\nimport contextlib\nimport datetime\nimport heapq\nimport itertools\nimport os  # noqa\nimport pathlib\nimport pickle\nimport re\nimport time\nimport warnings\nfrom collections import defaultdict\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import (\n    DefaultDict,\n    Dict,\n    Iterable,\n    Iterator,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Union,\n    cast,\n)\n\nfrom yarl import URL\n\nfrom .abc import AbstractCookieJar, ClearCookiePredicate\nfrom .helpers import is_ip_address\nfrom .typedefs import LooseCookies, PathLike, StrOrURL\n\n__all__ = (\"CookieJar\", \"DummyCookieJar\")\n\n\nCookieItem = Union[str, \"Morsel[str]\"]\n\n# We cache these string methods here as their use is in performance critical code.\n_FORMAT_PATH = \"{}/{}\".format\n_FORMAT_DOMAIN_REVERSED = \"{1}.{0}\".format\n\n# The minimum number of scheduled cookie expirations before we start cleaning up\n# the expiration heap. This is a performance optimization to avoid cleaning up the\n# heap too often when there are only a few scheduled expirations.\n_MIN_SCHEDULED_COOKIE_EXPIRATION = 100\n\n\nclass CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        if type(request_url) is not URL:\n            warnings.warn(\n                \"filter_cookies expects yarl.URL instances only,\"\n                f\"and will stop working in 4.x, got {type(request_url)}\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))\n\n\nclass DummyCookieJar(AbstractCookieJar):\n    \"\"\"Implements a dummy cookie storage.\n\n    It can be used with the ClientSession when no cookie processing is needed.\n\n    \"\"\"\n\n    def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:\n        super().__init__(loop=loop)\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        while False:\n            yield None\n\n    def __len__(self) -> int:\n        return 0\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        pass\n\n    def clear_domain(self, domain: str) -> None:\n        pass\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        pass\n\n    def filter_cookies(self, request_url: URL) -> \"BaseCookie[str]\":\n        return SimpleCookie()\n",
            "header": {
                "file": {
                    "path": "aiohttp/cookiejar.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "3ffa4198",
                "new_commit_hash": "ef04bda5",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/cookiejar.py"
            },
            "plus_file": {
                "path": "b/aiohttp/cookiejar.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 9,
                            "length": 6
                        },
                        "new_range": {
                            "start": 9,
                            "length": 7
                        },
                        "section": "import pathlib"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "import pickle",
                                "type": "context"
                            },
                            {
                                "content": "import re",
                                "type": "context"
                            },
                            {
                                "content": "import time",
                                "type": "context"
                            },
                            {
                                "content": "import warnings",
                                "type": "added"
                            },
                            {
                                "content": "from collections import defaultdict",
                                "type": "context"
                            },
                            {
                                "content": "from http.cookies import BaseCookie, Morsel, SimpleCookie",
                                "type": "context"
                            },
                            {
                                "content": "from typing import (",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "aiohttp/cookiejar.py",
                            "type": "import",
                            "name": "warnings",
                            "content": "import warnings",
                            "ast_type_str": "Import",
                            "start_lineno": 12,
                            "end_lineno": 12,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 309,
                            "length": 7
                        },
                        "new_range": {
                            "start": 310,
                            "length": 14
                        },
                        "section": "class CookieJar(AbstractCookieJar):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        if not self._cookies:",
                                "type": "context"
                            },
                            {
                                "content": "            # Skip rest of function if no non-expired cookies.",
                                "type": "context"
                            },
                            {
                                "content": "            return filtered",
                                "type": "context"
                            },
                            {
                                "content": "        request_url = URL(request_url)",
                                "type": "deleted"
                            },
                            {
                                "content": "        if type(request_url) is not URL:",
                                "type": "added"
                            },
                            {
                                "content": "            warnings.warn(",
                                "type": "added"
                            },
                            {
                                "content": "                \"filter_cookies expects yarl.URL instances only,\"",
                                "type": "added"
                            },
                            {
                                "content": "                f\"and will stop working in 4.x, got {type(request_url)}\",",
                                "type": "added"
                            },
                            {
                                "content": "                DeprecationWarning,",
                                "type": "added"
                            },
                            {
                                "content": "                stacklevel=2,",
                                "type": "added"
                            },
                            {
                                "content": "            )",
                                "type": "added"
                            },
                            {
                                "content": "            request_url = URL(request_url)",
                                "type": "added"
                            },
                            {
                                "content": "        hostname = request_url.raw_host or \"\"",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        is_not_secure = request_url.scheme not in (\"https\", \"wss\")",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/cookiejar.py",
                            "type": "class",
                            "name": "CookieJar",
                            "content": "class CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 49,
                            "end_lineno": 449,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/cookiejar.py",
                            "type": "method",
                            "name": "CookieJar.filter_cookies",
                            "content": "class CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 300,
                            "end_lineno": 369,
                            "parent": {
                                "file_name": "aiohttp/cookiejar.py",
                                "type": "class",
                                "name": "CookieJar",
                                "content": "class CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 49,
                                "end_lineno": 449,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport datetime\nimport heapq\nimport itertools\nimport pathlib\nimport pickle\nimport unittest\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom operator import not_\nfrom unittest import mock\n\nimport pytest\nfrom freezegun import freeze_time\nfrom yarl import URL\n\nfrom aiohttp import CookieJar, DummyCookieJar\n\n\ndef dump_cookiejar() -> bytes:  # pragma: no cover\n    \"\"\"Create pickled data for test_pickle_format().\"\"\"\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send.__pytest_wrapped__.obj())\n    return pickle.dumps(cj._cookies, pickle.HIGHEST_PROTOCOL)\n\n\n@pytest.fixture\ndef cookies_to_send():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 2999 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_send_with_expired():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_receive():\n    return SimpleCookie(\n        \"unconstrained-cookie=first; Path=/; \"\n        \"domain-cookie=second; Domain=example.com; Path=/; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n        \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n        \"no-path-cookie=seventh; Domain=pathtest.com; \"\n        \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n        \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n    )\n\n\ndef test_date_parsing() -> None:\n    parse_func = CookieJar._parse_date\n    utc = datetime.timezone.utc\n\n    assert parse_func(\"\") is None\n\n    # 70 -> 1970\n    assert (\n        parse_func(\"Tue, 1 Jan 70 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # 10 -> 2010\n    assert (\n        parse_func(\"Tue, 1 Jan 10 00:00:00 GMT\")\n        == datetime.datetime(2010, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No day of week string\n    assert (\n        parse_func(\"1 Jan 1970 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No timezone string\n    assert (\n        parse_func(\"Tue, 1 Jan 1970 00:00:00\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No year\n    assert parse_func(\"Tue, 1 Jan 00:00:00 GMT\") is None\n\n    # No month\n    assert parse_func(\"Tue, 1 1970 00:00:00 GMT\") is None\n\n    # No day of month\n    assert parse_func(\"Tue, Jan 1970 00:00:00 GMT\") is None\n\n    # No time\n    assert parse_func(\"Tue, 1 Jan 1970 GMT\") is None\n\n    # Invalid day of month\n    assert parse_func(\"Tue, 0 Jan 1970 00:00:00 GMT\") is None\n\n    # Invalid year\n    assert parse_func(\"Tue, 1 Jan 1500 00:00:00 GMT\") is None\n\n    # Invalid time\n    assert parse_func(\"Tue, 1 Jan 1970 77:88:99 GMT\") is None\n\n\ndef test_domain_matching() -> None:\n    test_func = CookieJar._is_domain_match\n\n    assert test_func(\"test.com\", \"test.com\")\n    assert test_func(\"test.com\", \"sub.test.com\")\n\n    assert not test_func(\"test.com\", \"\")\n    assert not test_func(\"test.com\", \"test.org\")\n    assert not test_func(\"diff-test.com\", \"test.com\")\n    assert not test_func(\"test.com\", \"diff-test.com\")\n    assert not test_func(\"test.com\", \"127.0.0.1\")\n\n\nasync def test_constructor(loop, cookies_to_send, cookies_to_receive) -> None:\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(cookies_to_send)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send\n    assert jar_cookies == expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_constructor_with_expired(\n    loop, cookies_to_send_with_expired, cookies_to_receive\n) -> None:\n    jar = CookieJar()\n    jar.update_cookies(cookies_to_send_with_expired)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send_with_expired\n    assert jar_cookies != expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_save_load(tmp_path, loop, cookies_to_send, cookies_to_receive) -> None:\n    file_path = pathlib.Path(str(tmp_path)) / \"aiohttp.test.cookie\"\n\n    # export cookie jar\n    jar_save = CookieJar(loop=loop)\n    jar_save.update_cookies(cookies_to_receive)\n    jar_save.save(file_path=file_path)\n\n    jar_load = CookieJar(loop=loop)\n    jar_load.load(file_path=file_path)\n\n    jar_test = SimpleCookie()\n    for cookie in jar_load:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == cookies_to_receive\n\n\nasync def test_update_cookie_with_unicode_domain(loop) -> None:\n    cookies = (\n        \"idna-domain-first=first; Domain=xn--9caa.com; Path=/;\",\n        \"idna-domain-second=second; Domain=xn--9caa.com; Path=/;\",\n    )\n\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(SimpleCookie(cookies[0]), URL(\"http://éé.com/\"))\n    jar.update_cookies(SimpleCookie(cookies[1]), URL(\"http://xn--9caa.com/\"))\n\n    jar_test = SimpleCookie()\n    for cookie in jar:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == SimpleCookie(\" \".join(cookies))\n\n\nasync def test_filter_cookie_with_unicode_domain(loop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(\n        SimpleCookie(\"idna-domain-first=first; Domain=xn--9caa.com; Path=/; \")\n    )\n    assert len(jar.filter_cookies(URL(\"http://éé.com\"))) == 1\n    assert len(jar.filter_cookies(URL(\"http://xn--9caa.com\"))) == 1\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"expected_cookies\"),\n    (\n        (\n            \"http://pathtest.com/one/two/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two/three/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://test1.example.com/\",\n            (\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/\",\n            (\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n            ),\n        ),\n    ),\n)\nasync def test_filter_cookies_with_domain_path_lookup_multilevelpath(\n    loop,\n    url,\n    expected_cookies,\n) -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n    jar.update_cookies(cookies)\n    cookies = jar.filter_cookies(URL(url))\n\n    assert len(cookies) == len(expected_cookies)\n    for c in cookies:\n        assert c in expected_cookies\n\n\nasync def test_domain_filter_ip_cookie_send() -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n    jar.update_cookies(cookies)\n    cookies_sent = jar.filter_cookies(URL(\"http://1.2.3.4/\")).output(header=\"Cookie:\")\n    assert cookies_sent == \"Cookie: shared-cookie=first\"\n\n\nasync def test_domain_filter_ip_cookie_receive(cookies_to_receive) -> None:\n    jar = CookieJar()\n\n    jar.update_cookies(cookies_to_receive, URL(\"http://1.2.3.4/\"))\n    assert len(jar) == 0\n\n\n@pytest.mark.parametrize(\n    (\"cookies\", \"expected\", \"quote_bool\"),\n    [\n        (\n            \"shared-cookie=first; ip-cookie=second; Domain=127.0.0.1;\",\n            \"Cookie: ip-cookie=second\\r\\nCookie: shared-cookie=first\",\n            True,\n        ),\n        ('ip-cookie=\"second\"; Domain=127.0.0.1;', 'Cookie: ip-cookie=\"second\"', True),\n        (\"custom-cookie=value/one;\", 'Cookie: custom-cookie=\"value/one\"', True),\n        (\"custom-cookie=value1;\", \"Cookie: custom-cookie=value1\", True),\n        (\"custom-cookie=value/one;\", \"Cookie: custom-cookie=value/one\", False),\n    ],\n    ids=(\n        \"IP domain preserved\",\n        \"no shared cookie\",\n        \"quoted cookie with special char\",\n        \"quoted cookie w/o special char\",\n        \"unquoted cookie with special char\",\n    ),\n)\nasync def test_quotes_correctly_based_on_input(\n    loop, cookies, expected, quote_bool\n) -> None:\n    jar = CookieJar(unsafe=True, quote_cookie=quote_bool)\n    jar.update_cookies(SimpleCookie(cookies))\n    cookies_sent = jar.filter_cookies(URL(\"http://127.0.0.1/\")).output(header=\"Cookie:\")\n    assert cookies_sent == expected\n\n\nasync def test_ignore_domain_ending_with_dot(loop) -> None:\n    jar = CookieJar(loop=loop, unsafe=True)\n    jar.update_cookies(\n        SimpleCookie(\"cookie=val; Domain=example.com.;\"), URL(\"http://www.example.com\")\n    )\n    cookies_sent = jar.filter_cookies(URL(\"http://www.example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"Cookie: cookie=val\"\n    cookies_sent = jar.filter_cookies(URL(\"http://example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"\"\n\n\nclass TestCookieJarBase(unittest.TestCase):\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n        # N.B. those need to be overridden in child test cases\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def tearDown(self):\n        self.loop.close()\n\n    def request_reply_with_same_url(self, url):\n        self.jar.update_cookies(self.cookies_to_send)\n        cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        self.jar.update_cookies(self.cookies_to_receive, URL(url))\n        cookies_received = SimpleCookie()\n        for cookie in self.jar:\n            dict.__setitem__(cookies_received, cookie.key, cookie)\n\n        self.jar.clear()\n\n        return cookies_sent, cookies_received\n\n\nclass TestCookieJarSafe(TestCookieJarBase):\n    def setUp(self):\n        super().setUp()\n\n        self.cookies_to_send = SimpleCookie(\n            \"shared-cookie=first; \"\n            \"domain-cookie=second; Domain=example.com; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n            \"different-domain-cookie=sixth; Domain=different.org; \"\n            \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n            \"no-path-cookie=eighth; Domain=pathtest.com; \"\n            \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n            \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n            \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n            \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n            \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n            \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n            \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n            \" Max-Age=60; \"\n            \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n            \" Max-Age=string; \"\n            \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n            \" Expires=string;\"\n        )\n\n        self.cookies_to_receive = SimpleCookie(\n            \"unconstrained-cookie=first; Path=/; \"\n            \"domain-cookie=second; Domain=example.com; Path=/; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n            \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n            \"no-path-cookie=seventh; Domain=pathtest.com; \"\n            \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n            \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n        )\n\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def timed_request(self, url, update_time, send_time):\n        if isinstance(update_time, int):\n            update_time = datetime.timedelta(seconds=update_time)\n        elif isinstance(update_time, float):\n            update_time = datetime.datetime.fromtimestamp(update_time)\n        if isinstance(send_time, int):\n            send_time = datetime.timedelta(seconds=send_time)\n        elif isinstance(send_time, float):\n            send_time = datetime.datetime.fromtimestamp(send_time)\n\n        with freeze_time(update_time):\n            self.jar.update_cookies(self.cookies_to_send)\n\n        with freeze_time(send_time):\n            cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        return cookies_sent\n\n    def test_domain_filter_same_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_same_host_and_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://test1.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n    def test_domain_filter_same_host_diff_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_diff_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.org/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()), {\"shared-cookie\", \"different-domain-cookie\"}\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"different-domain-cookie\"},\n        )\n\n    def test_domain_filter_host_only(self) -> None:\n        self.jar.update_cookies(self.cookies_to_receive, URL(\"http://example.com/\"))\n        sub_cookie = SimpleCookie(\"subdomain=spam; Path=/;\")\n        self.jar.update_cookies(sub_cookie, URL(\"http://foo.example.com/\"))\n\n        cookies_sent = self.jar.filter_cookies(URL(\"http://foo.example.com/\"))\n        self.assertIn(\"subdomain\", set(cookies_sent.keys()))\n        self.assertNotIn(\"unconstrained-cookie\", set(cookies_sent.keys()))\n\n    def test_secure_filter(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"https://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"secure-cookie\"})\n\n    def test_path_filter_root(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_filter_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/one/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\", \"path2-cookie\"},\n        )\n\n    def test_path_filter_file(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n            },\n        )\n\n    def test_path_filter_subfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_subsubfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/three/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_different_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/hundred/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_value(self) -> None:\n        _, cookies_received = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"no-path-cookie\",\n                \"path-cookie\",\n                \"wrong-path-cookie\",\n            },\n        )\n\n        self.assertEqual(cookies_received[\"no-path-cookie\"][\"path\"], \"/\")\n        self.assertEqual(cookies_received[\"path-cookie\"][\"path\"], \"/somepath\")\n        self.assertEqual(cookies_received[\"wrong-path-cookie\"][\"path\"], \"/\")\n\n    def test_expires(self) -> None:\n        ts_before = datetime.datetime(\n            1975, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        ts_after = datetime.datetime(\n            2030, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_before\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"expires-cookie\"})\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_after\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_max_age(self) -> None:\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 1000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"max-age-cookie\"})\n\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 2000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_invalid_values(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://invalid-values.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"invalid-max-age-cookie\", \"invalid-expires-cookie\"},\n        )\n\n        cookie = cookies_sent[\"invalid-max-age-cookie\"]\n        self.assertEqual(cookie[\"max-age\"], \"\")\n\n        cookie = cookies_sent[\"invalid-expires-cookie\"]\n        self.assertEqual(cookie[\"expires\"], \"\")\n\n    def test_cookie_not_expired_when_added_after_removal(self) -> None:\n        # Test case for https://github.com/aio-libs/aiohttp/issues/2084\n        timestamps = [\n            533588.993,\n            533588.993,\n            533588.993,\n            533588.993,\n            533589.093,\n            533589.093,\n        ]\n\n        loop = mock.Mock()\n        loop.time.side_effect = itertools.chain(\n            timestamps, itertools.cycle([timestamps[-1]])\n        )\n\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        # Remove `foo` cookie.\n        jar.update_cookies(SimpleCookie('foo=\"\"; Max-Age=0'))\n        # Set `foo` cookie to `bar`.\n        jar.update_cookies(SimpleCookie('foo=\"bar\"'))\n\n        # Assert that there is a cookie.\n        assert len(jar) == 1\n\n    def test_path_filter_diff_folder_same_name(self) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        self.assertEqual(len(jar), 2)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n    def test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order(\n        self,\n    ) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=two; Domain=pathtest.com; Path=/second; \")\n        )\n        self.assertEqual(len(jar), 3)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/second\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"two\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n\nasync def test_dummy_cookie_jar() -> None:\n    cookie = SimpleCookie(\"foo=bar; Domain=example.com;\")\n    dummy_jar = DummyCookieJar()\n    assert len(dummy_jar) == 0\n    dummy_jar.update_cookies(cookie)\n    assert len(dummy_jar) == 0\n    with pytest.raises(StopIteration):\n        next(iter(dummy_jar))\n    assert not dummy_jar.filter_cookies(URL(\"http://example.com/\"))\n    dummy_jar.clear()\n\n\nasync def test_loose_cookies_types() -> None:\n    jar = CookieJar()\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", Morsel())],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": Morsel()},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        jar.update_cookies(cookies=loose_cookies_type)\n\n\nasync def test_cookie_jar_clear_all():\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    sut.update_cookies(cookie)\n\n    sut.clear()\n    assert len(sut) == 0\n\n\nasync def test_cookie_jar_clear_expired():\n    sut = CookieJar()\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        sut.update_cookies(cookie)\n\n    for _ in range(2):\n        sut.clear(not_)\n        with freeze_time(\"1980-01-01\"):\n            assert len(sut) == 0\n\n\nasync def test_cookie_jar_expired_changes() -> None:\n    \"\"\"Test that expire time changes are handled as expected.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_noon = SimpleCookie()\n    cookie_noon[\"foo\"] = \"bar\"\n    cookie_noon[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    cookie_one_pm = SimpleCookie()\n    cookie_one_pm[\"foo\"] = \"bar\"\n    cookie_one_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 13:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n        jar.update_cookies(cookie_noon)\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_eleven_am)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_one_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 13:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 14:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n\n\nasync def test_cookie_jar_duplicates_with_expire_heap() -> None:\n    \"\"\"Test that duplicate cookies do not grow the expires heap.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n\n        for _ in range(10):\n            jar.update_cookies(cookie_eleven_am)\n\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        assert len(jar._expire_heap) == 1\n\n        freezer.move_to(\"1990-01-01 16:00:00+00:00\")\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n        assert len(jar._expire_heap) == 0\n\n\nasync def test_cookie_jar_filter_cookies_expires() -> None:\n    \"\"\"Test that calling filter_cookies will expire stale cookies.\"\"\"\n    jar = CookieJar()\n    assert len(jar) == 0\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        jar.update_cookies(cookie)\n\n    assert len(jar) == 1\n\n    # filter_cookies should expire stale cookies\n    jar.filter_cookies(URL(\"http://any.com/\"))\n\n    assert len(jar) == 0\n\n\nasync def test_cookie_jar_heap_cleanup() -> None:\n    \"\"\"Test that the heap gets cleaned up when there are many old expirations.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        start_time = datetime.datetime(\n            1990, 1, 1, 10, 0, 0, tzinfo=datetime.timezone.utc\n        )\n        for i in range(min_cookies_to_cleanup):\n            cookie = SimpleCookie()\n            cookie[\"foo\"] = \"bar\"\n            cookie[\"foo\"][\"expires\"] = (\n                start_time + datetime.timedelta(seconds=i)\n            ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n            jar.update_cookies(cookie)\n            assert len(jar._expire_heap) == i + 1\n\n        assert len(jar._expire_heap) == min_cookies_to_cleanup\n\n        # Now that we reached the minimum number of cookies to cleanup,\n        # add one more cookie to trigger the cleanup\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"expires\"] = (\n            start_time + datetime.timedelta(seconds=i + 1)\n        ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n        jar.update_cookies(cookie)\n\n        # Verify that the heap has been cleaned up\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 1\n\n\nasync def test_cookie_jar_heap_maintains_order_after_cleanup() -> None:\n    \"\"\"Test that order is maintained after cleanup.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        for hour in (12, 13):\n            for i in range(min_cookies_to_cleanup):\n                cookie = SimpleCookie()\n                cookie[\"foo\"] = \"bar\"\n                cookie[\"foo\"][\"domain\"] = f\"example{i}.com\"\n                cookie[\"foo\"][\"expires\"] = f\"Tue, 1 Jan 1990 {hour}:00:00 GMT\"\n                jar.update_cookies(cookie)\n\n        # Get the jar into a state where the next cookie will trigger the cleanup\n        assert len(jar._expire_heap) == min_cookies_to_cleanup * 2\n        assert len(jar._expirations) == min_cookies_to_cleanup\n\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"domain\"] = \"example0.com\"\n        cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n        jar.update_cookies(cookie)\n\n        assert len(jar) == 100\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 100\n\n        # Verify that the heap is still ordered\n        heap_before = jar._expire_heap.copy()\n        heapq.heapify(jar._expire_heap)\n        assert heap_before == jar._expire_heap\n\n\nasync def test_cookie_jar_clear_domain() -> None:\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"domain_cookie\"] = \"value\"\n    cookie[\"domain_cookie\"][\"domain\"] = \"example.com\"\n    cookie[\"subdomain_cookie\"] = \"value\"\n    cookie[\"subdomain_cookie\"][\"domain\"] = \"test.example.com\"\n    sut.update_cookies(cookie)\n\n    sut.clear_domain(\"example.com\")\n    iterator = iter(sut)\n    morsel = next(iterator)\n    assert morsel.key == \"foo\"\n    assert morsel.value == \"bar\"\n    with pytest.raises(StopIteration):\n        next(iterator)\n\n\nasync def test_pickle_format(cookies_to_send) -> None:\n    \"\"\"Test if cookiejar pickle format breaks.\n\n    If this test fails, it may indicate that saved cookiejars will stop working.\n    If that happens then:\n        1. Avoid releasing the change in a bugfix release.\n        2. Try to include a migration script in the release notes (example below).\n        3. Use dump_cookiejar() at the top of this file to update `pickled`.\n\n    Depending on the changes made, a migration script might look like:\n        import pickle\n        with file_path.open(\"rb\") as f:\n            cookies = pickle.load(f)\n\n        morsels = [(name, m) for c in cookies.values() for name, m in c.items()]\n        cookies.clear()\n        for name, m in morsels:\n            cookies[(m[\"domain\"], m[\"path\"])][name] = m\n\n        with file_path.open(\"wb\") as f:\n            pickle.dump(cookies, f, pickle.HIGHEST_PROTOCOL)\n    \"\"\"\n    pickled = b\"\\x80\\x04\\x95\\xc8\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x8c\\x0bcollections\\x94\\x8c\\x0bdefaultdict\\x94\\x93\\x94\\x8c\\x0chttp.cookies\\x94\\x8c\\x0cSimpleCookie\\x94\\x93\\x94\\x85\\x94R\\x94(\\x8c\\x00\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rshared-cookie\\x94h\\x03\\x8c\\x06Morsel\\x94\\x93\\x94)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\x01/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x08\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(\\x8c\\x03key\\x94h\\x0b\\x8c\\x05value\\x94\\x8c\\x05first\\x94\\x8c\\x0bcoded_value\\x94h\\x1cubs\\x8c\\x0bexample.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\rdomain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x1e\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah!h\\x1b\\x8c\\x06second\\x94h\\x1dh-ub\\x8c\\x14dotted-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0bexample.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah.h\\x1b\\x8c\\x05fifth\\x94h\\x1dh;ubu\\x8c\\x11test1.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h<\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah?h\\x1b\\x8c\\x05third\\x94h\\x1dhKubs\\x8c\\x11test2.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hL\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahOh\\x1b\\x8c\\x06fourth\\x94h\\x1dh[ubs\\x8c\\rdifferent.org\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x17different-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\\\\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah_h\\x1b\\x8c\\x05sixth\\x94h\\x1dhkubs\\x8c\\nsecure.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rsecure-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hl\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94\\x88\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahoh\\x1b\\x8c\\x07seventh\\x94h\\x1dh{ubs\\x8c\\x0cpathtest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0eno-path-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h|\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x7fh\\x1b\\x8c\\x06eighth\\x94h\\x1dh\\x8bub\\x8c\\x0cpath1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x8ch\\x1b\\x8c\\x05ninth\\x94h\\x1dh\\x99ubu\\x8c\\x0cpathtest.com\\x94\\x8c\\x04/one\\x94\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0cpath2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x9b\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x9a\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x9eh\\x1b\\x8c\\x05tenth\\x94h\\x1dh\\xaaubs\\x8c\\x0cpathtest.com\\x94\\x8c\\x08/one/two\\x94\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0cpath3-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\xac\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xab\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xafh\\x1b\\x8c\\x08eleventh\\x94h\\x1dh\\xbbub\\x8c\\x0cpath4-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\t/one/two/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xbch\\x1b\\x8c\\x07twelfth\\x94h\\x1dh\\xcaubu\\x8c\\x0fexpirestest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0eexpires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94\\x8c\\x1cTue, 1 Jan 2999 12:00:00 GMT\\x94\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xcb\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xceh\\x1b\\x8c\\nthirteenth\\x94h\\x1dh\\xdbubs\\x8c\\x0emaxagetest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0emax-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xdc\\x8c\\x07max-age\\x94\\x8c\\x0260\\x94\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xdfh\\x1b\\x8c\\nfourteenth\\x94h\\x1dh\\xecubs\\x8c\\x12invalid-values.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x16invalid-max-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xed\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xf0h\\x1b\\x8c\\tfifteenth\\x94h\\x1dh\\xfcub\\x8c\\x16invalid-expires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x12invalid-values.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xfdh\\x1b\\x8c\\tsixteenth\\x94h\\x1dj\\n\\x01\\x00\\x00ubuu.\"\n    cookies = pickle.loads(pickled)\n\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send)\n\n    assert cookies == cj._cookies\n\n\n@pytest.mark.parametrize(\n    \"url\",\n    [\n        \"http://127.0.0.1/index.html\",\n        URL(\"http://127.0.0.1/index.html\"),\n        [\"http://127.0.0.1/index.html\"],\n        [URL(\"http://127.0.0.1/index.html\")],\n    ],\n)\nasync def test_treat_as_secure_origin_init(url) -> None:\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=url)\n    assert jar._treat_as_secure_origin == [URL(\"http://127.0.0.1\")]\n\n\nasync def test_treat_as_secure_origin() -> None:\n    endpoint = URL(\"http://127.0.0.1/\")\n\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint])\n    secure_cookie = SimpleCookie(\n        \"cookie-key=cookie-value; HttpOnly; Path=/; Secure\",\n    )\n\n    jar.update_cookies(\n        secure_cookie,\n        endpoint,\n    )\n\n    assert len(jar) == 1\n    filtered_cookies = jar.filter_cookies(request_url=endpoint)\n    assert len(filtered_cookies) == 1\n",
            "new_file_content": "import asyncio\nimport datetime\nimport heapq\nimport itertools\nimport pathlib\nimport pickle\nimport unittest\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom operator import not_\nfrom unittest import mock\n\nimport pytest\nfrom freezegun import freeze_time\nfrom yarl import URL\n\nfrom aiohttp import CookieJar, DummyCookieJar\n\n\ndef dump_cookiejar() -> bytes:  # pragma: no cover\n    \"\"\"Create pickled data for test_pickle_format().\"\"\"\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send.__pytest_wrapped__.obj())\n    return pickle.dumps(cj._cookies, pickle.HIGHEST_PROTOCOL)\n\n\n@pytest.fixture\ndef cookies_to_send():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 2999 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_send_with_expired():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_receive():\n    return SimpleCookie(\n        \"unconstrained-cookie=first; Path=/; \"\n        \"domain-cookie=second; Domain=example.com; Path=/; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n        \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n        \"no-path-cookie=seventh; Domain=pathtest.com; \"\n        \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n        \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n    )\n\n\ndef test_date_parsing() -> None:\n    parse_func = CookieJar._parse_date\n    utc = datetime.timezone.utc\n\n    assert parse_func(\"\") is None\n\n    # 70 -> 1970\n    assert (\n        parse_func(\"Tue, 1 Jan 70 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # 10 -> 2010\n    assert (\n        parse_func(\"Tue, 1 Jan 10 00:00:00 GMT\")\n        == datetime.datetime(2010, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No day of week string\n    assert (\n        parse_func(\"1 Jan 1970 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No timezone string\n    assert (\n        parse_func(\"Tue, 1 Jan 1970 00:00:00\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No year\n    assert parse_func(\"Tue, 1 Jan 00:00:00 GMT\") is None\n\n    # No month\n    assert parse_func(\"Tue, 1 1970 00:00:00 GMT\") is None\n\n    # No day of month\n    assert parse_func(\"Tue, Jan 1970 00:00:00 GMT\") is None\n\n    # No time\n    assert parse_func(\"Tue, 1 Jan 1970 GMT\") is None\n\n    # Invalid day of month\n    assert parse_func(\"Tue, 0 Jan 1970 00:00:00 GMT\") is None\n\n    # Invalid year\n    assert parse_func(\"Tue, 1 Jan 1500 00:00:00 GMT\") is None\n\n    # Invalid time\n    assert parse_func(\"Tue, 1 Jan 1970 77:88:99 GMT\") is None\n\n\ndef test_domain_matching() -> None:\n    test_func = CookieJar._is_domain_match\n\n    assert test_func(\"test.com\", \"test.com\")\n    assert test_func(\"test.com\", \"sub.test.com\")\n\n    assert not test_func(\"test.com\", \"\")\n    assert not test_func(\"test.com\", \"test.org\")\n    assert not test_func(\"diff-test.com\", \"test.com\")\n    assert not test_func(\"test.com\", \"diff-test.com\")\n    assert not test_func(\"test.com\", \"127.0.0.1\")\n\n\nasync def test_constructor(loop, cookies_to_send, cookies_to_receive) -> None:\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(cookies_to_send)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send\n    assert jar_cookies == expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_constructor_with_expired(\n    loop, cookies_to_send_with_expired, cookies_to_receive\n) -> None:\n    jar = CookieJar()\n    jar.update_cookies(cookies_to_send_with_expired)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send_with_expired\n    assert jar_cookies != expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_save_load(tmp_path, loop, cookies_to_send, cookies_to_receive) -> None:\n    file_path = pathlib.Path(str(tmp_path)) / \"aiohttp.test.cookie\"\n\n    # export cookie jar\n    jar_save = CookieJar(loop=loop)\n    jar_save.update_cookies(cookies_to_receive)\n    jar_save.save(file_path=file_path)\n\n    jar_load = CookieJar(loop=loop)\n    jar_load.load(file_path=file_path)\n\n    jar_test = SimpleCookie()\n    for cookie in jar_load:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == cookies_to_receive\n\n\nasync def test_update_cookie_with_unicode_domain(loop) -> None:\n    cookies = (\n        \"idna-domain-first=first; Domain=xn--9caa.com; Path=/;\",\n        \"idna-domain-second=second; Domain=xn--9caa.com; Path=/;\",\n    )\n\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(SimpleCookie(cookies[0]), URL(\"http://éé.com/\"))\n    jar.update_cookies(SimpleCookie(cookies[1]), URL(\"http://xn--9caa.com/\"))\n\n    jar_test = SimpleCookie()\n    for cookie in jar:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == SimpleCookie(\" \".join(cookies))\n\n\nasync def test_filter_cookie_with_unicode_domain(loop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(\n        SimpleCookie(\"idna-domain-first=first; Domain=xn--9caa.com; Path=/; \")\n    )\n    assert len(jar.filter_cookies(URL(\"http://éé.com\"))) == 1\n    assert len(jar.filter_cookies(URL(\"http://xn--9caa.com\"))) == 1\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"expected_cookies\"),\n    (\n        (\n            \"http://pathtest.com/one/two/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two/three/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://test1.example.com/\",\n            (\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/\",\n            (\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n            ),\n        ),\n    ),\n)\nasync def test_filter_cookies_with_domain_path_lookup_multilevelpath(\n    loop,\n    url,\n    expected_cookies,\n) -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n    jar.update_cookies(cookies)\n    cookies = jar.filter_cookies(URL(url))\n\n    assert len(cookies) == len(expected_cookies)\n    for c in cookies:\n        assert c in expected_cookies\n\n\nasync def test_filter_cookies_str_deprecated(loop: asyncio.AbstractEventLoop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(SimpleCookie(\"shared-cookie=first; Domain=example.com;\"))\n    with pytest.warns(DeprecationWarning):\n        jar.filter_cookies(\"http://éé.com\")\n\n\nasync def test_domain_filter_ip_cookie_send() -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n    jar.update_cookies(cookies)\n    cookies_sent = jar.filter_cookies(URL(\"http://1.2.3.4/\")).output(header=\"Cookie:\")\n    assert cookies_sent == \"Cookie: shared-cookie=first\"\n\n\nasync def test_domain_filter_ip_cookie_receive(cookies_to_receive) -> None:\n    jar = CookieJar()\n\n    jar.update_cookies(cookies_to_receive, URL(\"http://1.2.3.4/\"))\n    assert len(jar) == 0\n\n\n@pytest.mark.parametrize(\n    (\"cookies\", \"expected\", \"quote_bool\"),\n    [\n        (\n            \"shared-cookie=first; ip-cookie=second; Domain=127.0.0.1;\",\n            \"Cookie: ip-cookie=second\\r\\nCookie: shared-cookie=first\",\n            True,\n        ),\n        ('ip-cookie=\"second\"; Domain=127.0.0.1;', 'Cookie: ip-cookie=\"second\"', True),\n        (\"custom-cookie=value/one;\", 'Cookie: custom-cookie=\"value/one\"', True),\n        (\"custom-cookie=value1;\", \"Cookie: custom-cookie=value1\", True),\n        (\"custom-cookie=value/one;\", \"Cookie: custom-cookie=value/one\", False),\n    ],\n    ids=(\n        \"IP domain preserved\",\n        \"no shared cookie\",\n        \"quoted cookie with special char\",\n        \"quoted cookie w/o special char\",\n        \"unquoted cookie with special char\",\n    ),\n)\nasync def test_quotes_correctly_based_on_input(\n    loop, cookies, expected, quote_bool\n) -> None:\n    jar = CookieJar(unsafe=True, quote_cookie=quote_bool)\n    jar.update_cookies(SimpleCookie(cookies))\n    cookies_sent = jar.filter_cookies(URL(\"http://127.0.0.1/\")).output(header=\"Cookie:\")\n    assert cookies_sent == expected\n\n\nasync def test_ignore_domain_ending_with_dot(loop) -> None:\n    jar = CookieJar(loop=loop, unsafe=True)\n    jar.update_cookies(\n        SimpleCookie(\"cookie=val; Domain=example.com.;\"), URL(\"http://www.example.com\")\n    )\n    cookies_sent = jar.filter_cookies(URL(\"http://www.example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"Cookie: cookie=val\"\n    cookies_sent = jar.filter_cookies(URL(\"http://example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"\"\n\n\nclass TestCookieJarBase(unittest.TestCase):\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n        # N.B. those need to be overridden in child test cases\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def tearDown(self):\n        self.loop.close()\n\n    def request_reply_with_same_url(self, url):\n        self.jar.update_cookies(self.cookies_to_send)\n        cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        self.jar.update_cookies(self.cookies_to_receive, URL(url))\n        cookies_received = SimpleCookie()\n        for cookie in self.jar:\n            dict.__setitem__(cookies_received, cookie.key, cookie)\n\n        self.jar.clear()\n\n        return cookies_sent, cookies_received\n\n\nclass TestCookieJarSafe(TestCookieJarBase):\n    def setUp(self):\n        super().setUp()\n\n        self.cookies_to_send = SimpleCookie(\n            \"shared-cookie=first; \"\n            \"domain-cookie=second; Domain=example.com; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n            \"different-domain-cookie=sixth; Domain=different.org; \"\n            \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n            \"no-path-cookie=eighth; Domain=pathtest.com; \"\n            \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n            \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n            \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n            \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n            \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n            \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n            \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n            \" Max-Age=60; \"\n            \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n            \" Max-Age=string; \"\n            \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n            \" Expires=string;\"\n        )\n\n        self.cookies_to_receive = SimpleCookie(\n            \"unconstrained-cookie=first; Path=/; \"\n            \"domain-cookie=second; Domain=example.com; Path=/; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n            \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n            \"no-path-cookie=seventh; Domain=pathtest.com; \"\n            \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n            \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n        )\n\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def timed_request(self, url, update_time, send_time):\n        if isinstance(update_time, int):\n            update_time = datetime.timedelta(seconds=update_time)\n        elif isinstance(update_time, float):\n            update_time = datetime.datetime.fromtimestamp(update_time)\n        if isinstance(send_time, int):\n            send_time = datetime.timedelta(seconds=send_time)\n        elif isinstance(send_time, float):\n            send_time = datetime.datetime.fromtimestamp(send_time)\n\n        with freeze_time(update_time):\n            self.jar.update_cookies(self.cookies_to_send)\n\n        with freeze_time(send_time):\n            cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        return cookies_sent\n\n    def test_domain_filter_same_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_same_host_and_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://test1.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n    def test_domain_filter_same_host_diff_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_diff_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.org/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()), {\"shared-cookie\", \"different-domain-cookie\"}\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"different-domain-cookie\"},\n        )\n\n    def test_domain_filter_host_only(self) -> None:\n        self.jar.update_cookies(self.cookies_to_receive, URL(\"http://example.com/\"))\n        sub_cookie = SimpleCookie(\"subdomain=spam; Path=/;\")\n        self.jar.update_cookies(sub_cookie, URL(\"http://foo.example.com/\"))\n\n        cookies_sent = self.jar.filter_cookies(URL(\"http://foo.example.com/\"))\n        self.assertIn(\"subdomain\", set(cookies_sent.keys()))\n        self.assertNotIn(\"unconstrained-cookie\", set(cookies_sent.keys()))\n\n    def test_secure_filter(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"https://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"secure-cookie\"})\n\n    def test_path_filter_root(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_filter_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/one/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\", \"path2-cookie\"},\n        )\n\n    def test_path_filter_file(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n            },\n        )\n\n    def test_path_filter_subfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_subsubfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/three/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_different_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/hundred/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_value(self) -> None:\n        _, cookies_received = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"no-path-cookie\",\n                \"path-cookie\",\n                \"wrong-path-cookie\",\n            },\n        )\n\n        self.assertEqual(cookies_received[\"no-path-cookie\"][\"path\"], \"/\")\n        self.assertEqual(cookies_received[\"path-cookie\"][\"path\"], \"/somepath\")\n        self.assertEqual(cookies_received[\"wrong-path-cookie\"][\"path\"], \"/\")\n\n    def test_expires(self) -> None:\n        ts_before = datetime.datetime(\n            1975, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        ts_after = datetime.datetime(\n            2030, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_before\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"expires-cookie\"})\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_after\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_max_age(self) -> None:\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 1000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"max-age-cookie\"})\n\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 2000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_invalid_values(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://invalid-values.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"invalid-max-age-cookie\", \"invalid-expires-cookie\"},\n        )\n\n        cookie = cookies_sent[\"invalid-max-age-cookie\"]\n        self.assertEqual(cookie[\"max-age\"], \"\")\n\n        cookie = cookies_sent[\"invalid-expires-cookie\"]\n        self.assertEqual(cookie[\"expires\"], \"\")\n\n    def test_cookie_not_expired_when_added_after_removal(self) -> None:\n        # Test case for https://github.com/aio-libs/aiohttp/issues/2084\n        timestamps = [\n            533588.993,\n            533588.993,\n            533588.993,\n            533588.993,\n            533589.093,\n            533589.093,\n        ]\n\n        loop = mock.Mock()\n        loop.time.side_effect = itertools.chain(\n            timestamps, itertools.cycle([timestamps[-1]])\n        )\n\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        # Remove `foo` cookie.\n        jar.update_cookies(SimpleCookie('foo=\"\"; Max-Age=0'))\n        # Set `foo` cookie to `bar`.\n        jar.update_cookies(SimpleCookie('foo=\"bar\"'))\n\n        # Assert that there is a cookie.\n        assert len(jar) == 1\n\n    def test_path_filter_diff_folder_same_name(self) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        self.assertEqual(len(jar), 2)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n    def test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order(\n        self,\n    ) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=two; Domain=pathtest.com; Path=/second; \")\n        )\n        self.assertEqual(len(jar), 3)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/second\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"two\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n\nasync def test_dummy_cookie_jar() -> None:\n    cookie = SimpleCookie(\"foo=bar; Domain=example.com;\")\n    dummy_jar = DummyCookieJar()\n    assert len(dummy_jar) == 0\n    dummy_jar.update_cookies(cookie)\n    assert len(dummy_jar) == 0\n    with pytest.raises(StopIteration):\n        next(iter(dummy_jar))\n    assert not dummy_jar.filter_cookies(URL(\"http://example.com/\"))\n    dummy_jar.clear()\n\n\nasync def test_loose_cookies_types() -> None:\n    jar = CookieJar()\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", Morsel())],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": Morsel()},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        jar.update_cookies(cookies=loose_cookies_type)\n\n\nasync def test_cookie_jar_clear_all():\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    sut.update_cookies(cookie)\n\n    sut.clear()\n    assert len(sut) == 0\n\n\nasync def test_cookie_jar_clear_expired():\n    sut = CookieJar()\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        sut.update_cookies(cookie)\n\n    for _ in range(2):\n        sut.clear(not_)\n        with freeze_time(\"1980-01-01\"):\n            assert len(sut) == 0\n\n\nasync def test_cookie_jar_expired_changes() -> None:\n    \"\"\"Test that expire time changes are handled as expected.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_noon = SimpleCookie()\n    cookie_noon[\"foo\"] = \"bar\"\n    cookie_noon[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    cookie_one_pm = SimpleCookie()\n    cookie_one_pm[\"foo\"] = \"bar\"\n    cookie_one_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 13:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n        jar.update_cookies(cookie_noon)\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_eleven_am)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_one_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 13:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 14:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n\n\nasync def test_cookie_jar_duplicates_with_expire_heap() -> None:\n    \"\"\"Test that duplicate cookies do not grow the expires heap.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n\n        for _ in range(10):\n            jar.update_cookies(cookie_eleven_am)\n\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        assert len(jar._expire_heap) == 1\n\n        freezer.move_to(\"1990-01-01 16:00:00+00:00\")\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n        assert len(jar._expire_heap) == 0\n\n\nasync def test_cookie_jar_filter_cookies_expires() -> None:\n    \"\"\"Test that calling filter_cookies will expire stale cookies.\"\"\"\n    jar = CookieJar()\n    assert len(jar) == 0\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        jar.update_cookies(cookie)\n\n    assert len(jar) == 1\n\n    # filter_cookies should expire stale cookies\n    jar.filter_cookies(URL(\"http://any.com/\"))\n\n    assert len(jar) == 0\n\n\nasync def test_cookie_jar_heap_cleanup() -> None:\n    \"\"\"Test that the heap gets cleaned up when there are many old expirations.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        start_time = datetime.datetime(\n            1990, 1, 1, 10, 0, 0, tzinfo=datetime.timezone.utc\n        )\n        for i in range(min_cookies_to_cleanup):\n            cookie = SimpleCookie()\n            cookie[\"foo\"] = \"bar\"\n            cookie[\"foo\"][\"expires\"] = (\n                start_time + datetime.timedelta(seconds=i)\n            ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n            jar.update_cookies(cookie)\n            assert len(jar._expire_heap) == i + 1\n\n        assert len(jar._expire_heap) == min_cookies_to_cleanup\n\n        # Now that we reached the minimum number of cookies to cleanup,\n        # add one more cookie to trigger the cleanup\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"expires\"] = (\n            start_time + datetime.timedelta(seconds=i + 1)\n        ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n        jar.update_cookies(cookie)\n\n        # Verify that the heap has been cleaned up\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 1\n\n\nasync def test_cookie_jar_heap_maintains_order_after_cleanup() -> None:\n    \"\"\"Test that order is maintained after cleanup.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        for hour in (12, 13):\n            for i in range(min_cookies_to_cleanup):\n                cookie = SimpleCookie()\n                cookie[\"foo\"] = \"bar\"\n                cookie[\"foo\"][\"domain\"] = f\"example{i}.com\"\n                cookie[\"foo\"][\"expires\"] = f\"Tue, 1 Jan 1990 {hour}:00:00 GMT\"\n                jar.update_cookies(cookie)\n\n        # Get the jar into a state where the next cookie will trigger the cleanup\n        assert len(jar._expire_heap) == min_cookies_to_cleanup * 2\n        assert len(jar._expirations) == min_cookies_to_cleanup\n\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"domain\"] = \"example0.com\"\n        cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n        jar.update_cookies(cookie)\n\n        assert len(jar) == 100\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 100\n\n        # Verify that the heap is still ordered\n        heap_before = jar._expire_heap.copy()\n        heapq.heapify(jar._expire_heap)\n        assert heap_before == jar._expire_heap\n\n\nasync def test_cookie_jar_clear_domain() -> None:\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"domain_cookie\"] = \"value\"\n    cookie[\"domain_cookie\"][\"domain\"] = \"example.com\"\n    cookie[\"subdomain_cookie\"] = \"value\"\n    cookie[\"subdomain_cookie\"][\"domain\"] = \"test.example.com\"\n    sut.update_cookies(cookie)\n\n    sut.clear_domain(\"example.com\")\n    iterator = iter(sut)\n    morsel = next(iterator)\n    assert morsel.key == \"foo\"\n    assert morsel.value == \"bar\"\n    with pytest.raises(StopIteration):\n        next(iterator)\n\n\nasync def test_pickle_format(cookies_to_send) -> None:\n    \"\"\"Test if cookiejar pickle format breaks.\n\n    If this test fails, it may indicate that saved cookiejars will stop working.\n    If that happens then:\n        1. Avoid releasing the change in a bugfix release.\n        2. Try to include a migration script in the release notes (example below).\n        3. Use dump_cookiejar() at the top of this file to update `pickled`.\n\n    Depending on the changes made, a migration script might look like:\n        import pickle\n        with file_path.open(\"rb\") as f:\n            cookies = pickle.load(f)\n\n        morsels = [(name, m) for c in cookies.values() for name, m in c.items()]\n        cookies.clear()\n        for name, m in morsels:\n            cookies[(m[\"domain\"], m[\"path\"])][name] = m\n\n        with file_path.open(\"wb\") as f:\n            pickle.dump(cookies, f, pickle.HIGHEST_PROTOCOL)\n    \"\"\"\n    pickled = b\"\\x80\\x04\\x95\\xc8\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x8c\\x0bcollections\\x94\\x8c\\x0bdefaultdict\\x94\\x93\\x94\\x8c\\x0chttp.cookies\\x94\\x8c\\x0cSimpleCookie\\x94\\x93\\x94\\x85\\x94R\\x94(\\x8c\\x00\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rshared-cookie\\x94h\\x03\\x8c\\x06Morsel\\x94\\x93\\x94)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\x01/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x08\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(\\x8c\\x03key\\x94h\\x0b\\x8c\\x05value\\x94\\x8c\\x05first\\x94\\x8c\\x0bcoded_value\\x94h\\x1cubs\\x8c\\x0bexample.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\rdomain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x1e\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah!h\\x1b\\x8c\\x06second\\x94h\\x1dh-ub\\x8c\\x14dotted-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0bexample.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah.h\\x1b\\x8c\\x05fifth\\x94h\\x1dh;ubu\\x8c\\x11test1.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h<\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah?h\\x1b\\x8c\\x05third\\x94h\\x1dhKubs\\x8c\\x11test2.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hL\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahOh\\x1b\\x8c\\x06fourth\\x94h\\x1dh[ubs\\x8c\\rdifferent.org\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x17different-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\\\\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah_h\\x1b\\x8c\\x05sixth\\x94h\\x1dhkubs\\x8c\\nsecure.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rsecure-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hl\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94\\x88\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahoh\\x1b\\x8c\\x07seventh\\x94h\\x1dh{ubs\\x8c\\x0cpathtest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0eno-path-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h|\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x7fh\\x1b\\x8c\\x06eighth\\x94h\\x1dh\\x8bub\\x8c\\x0cpath1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x8ch\\x1b\\x8c\\x05ninth\\x94h\\x1dh\\x99ubu\\x8c\\x0cpathtest.com\\x94\\x8c\\x04/one\\x94\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0cpath2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x9b\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x9a\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x9eh\\x1b\\x8c\\x05tenth\\x94h\\x1dh\\xaaubs\\x8c\\x0cpathtest.com\\x94\\x8c\\x08/one/two\\x94\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0cpath3-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\xac\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xab\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xafh\\x1b\\x8c\\x08eleventh\\x94h\\x1dh\\xbbub\\x8c\\x0cpath4-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\t/one/two/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xbch\\x1b\\x8c\\x07twelfth\\x94h\\x1dh\\xcaubu\\x8c\\x0fexpirestest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0eexpires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94\\x8c\\x1cTue, 1 Jan 2999 12:00:00 GMT\\x94\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xcb\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xceh\\x1b\\x8c\\nthirteenth\\x94h\\x1dh\\xdbubs\\x8c\\x0emaxagetest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0emax-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xdc\\x8c\\x07max-age\\x94\\x8c\\x0260\\x94\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xdfh\\x1b\\x8c\\nfourteenth\\x94h\\x1dh\\xecubs\\x8c\\x12invalid-values.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x16invalid-max-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xed\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xf0h\\x1b\\x8c\\tfifteenth\\x94h\\x1dh\\xfcub\\x8c\\x16invalid-expires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x12invalid-values.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xfdh\\x1b\\x8c\\tsixteenth\\x94h\\x1dj\\n\\x01\\x00\\x00ubuu.\"\n    cookies = pickle.loads(pickled)\n\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send)\n\n    assert cookies == cj._cookies\n\n\n@pytest.mark.parametrize(\n    \"url\",\n    [\n        \"http://127.0.0.1/index.html\",\n        URL(\"http://127.0.0.1/index.html\"),\n        [\"http://127.0.0.1/index.html\"],\n        [URL(\"http://127.0.0.1/index.html\")],\n    ],\n)\nasync def test_treat_as_secure_origin_init(url) -> None:\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=url)\n    assert jar._treat_as_secure_origin == [URL(\"http://127.0.0.1\")]\n\n\nasync def test_treat_as_secure_origin() -> None:\n    endpoint = URL(\"http://127.0.0.1/\")\n\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint])\n    secure_cookie = SimpleCookie(\n        \"cookie-key=cookie-value; HttpOnly; Path=/; Secure\",\n    )\n\n    jar.update_cookies(\n        secure_cookie,\n        endpoint,\n    )\n\n    assert len(jar) == 1\n    filtered_cookies = jar.filter_cookies(request_url=endpoint)\n    assert len(filtered_cookies) == 1\n",
            "header": {
                "file": {
                    "path": "tests/test_cookiejar.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "248d0d41",
                "new_commit_hash": "bdcf54fa",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_cookiejar.py"
            },
            "plus_file": {
                "path": "b/tests/test_cookiejar.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 313,
                            "length": 6
                        },
                        "new_range": {
                            "start": 313,
                            "length": 13
                        },
                        "section": "async def test_filter_cookies_with_domain_path_lookup_multilevelpath("
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        assert c in expected_cookies",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_filter_cookies_str_deprecated(loop: asyncio.AbstractEventLoop) -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    jar = CookieJar()",
                                "type": "added"
                            },
                            {
                                "content": "    jar.update_cookies(SimpleCookie(\"shared-cookie=first; Domain=example.com;\"))",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.warns(DeprecationWarning):",
                                "type": "added"
                            },
                            {
                                "content": "        jar.filter_cookies(\"http://éé.com\")",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_domain_filter_ip_cookie_send() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    jar = CookieJar()",
                                "type": "context"
                            },
                            {
                                "content": "    cookies = SimpleCookie(",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_cookiejar.py",
                            "type": "function",
                            "name": "test_filter_cookies_str_deprecated",
                            "content": "async def test_filter_cookies_str_deprecated(loop: asyncio.AbstractEventLoop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(SimpleCookie(\"shared-cookie=first; Domain=example.com;\"))\n    with pytest.warns(DeprecationWarning):\n        jar.filter_cookies(\"http://éé.com\")",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 316,
                            "end_lineno": 320,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "e56a4fd45b813a8c41d09c88aaf3c73903935c71^",
    "new_commit_hash": "e56a4fd45b813a8c41d09c88aaf3c73903935c71",
    "commit_message": "[PR #3753/401c256 backport][3.11] Enforce URL for `cookie_jar.filter_cookies()` call (#9715)\n\nCo-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>",
    "commit_date": "2024-11-07T23:11:09Z",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "e56a4fd45b813a8c41d09c88aaf3c73903935c71",
    "test_file_codes": [
        "import asyncio\nimport datetime\nimport heapq\nimport itertools\nimport pathlib\nimport pickle\nimport unittest\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom operator import not_\nfrom unittest import mock\n\nimport pytest\nfrom freezegun import freeze_time\nfrom yarl import URL\n\nfrom aiohttp import CookieJar, DummyCookieJar\n\n\ndef dump_cookiejar() -> bytes:  # pragma: no cover\n    \"\"\"Create pickled data for test_pickle_format().\"\"\"\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send.__pytest_wrapped__.obj())\n    return pickle.dumps(cj._cookies, pickle.HIGHEST_PROTOCOL)\n\n\n@pytest.fixture\ndef cookies_to_send():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 2999 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_send_with_expired():\n    return SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n\n@pytest.fixture\ndef cookies_to_receive():\n    return SimpleCookie(\n        \"unconstrained-cookie=first; Path=/; \"\n        \"domain-cookie=second; Domain=example.com; Path=/; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n        \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n        \"no-path-cookie=seventh; Domain=pathtest.com; \"\n        \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n        \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n    )\n\n\ndef test_date_parsing() -> None:\n    parse_func = CookieJar._parse_date\n    utc = datetime.timezone.utc\n\n    assert parse_func(\"\") is None\n\n    # 70 -> 1970\n    assert (\n        parse_func(\"Tue, 1 Jan 70 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # 10 -> 2010\n    assert (\n        parse_func(\"Tue, 1 Jan 10 00:00:00 GMT\")\n        == datetime.datetime(2010, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No day of week string\n    assert (\n        parse_func(\"1 Jan 1970 00:00:00 GMT\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No timezone string\n    assert (\n        parse_func(\"Tue, 1 Jan 1970 00:00:00\")\n        == datetime.datetime(1970, 1, 1, tzinfo=utc).timestamp()\n    )\n\n    # No year\n    assert parse_func(\"Tue, 1 Jan 00:00:00 GMT\") is None\n\n    # No month\n    assert parse_func(\"Tue, 1 1970 00:00:00 GMT\") is None\n\n    # No day of month\n    assert parse_func(\"Tue, Jan 1970 00:00:00 GMT\") is None\n\n    # No time\n    assert parse_func(\"Tue, 1 Jan 1970 GMT\") is None\n\n    # Invalid day of month\n    assert parse_func(\"Tue, 0 Jan 1970 00:00:00 GMT\") is None\n\n    # Invalid year\n    assert parse_func(\"Tue, 1 Jan 1500 00:00:00 GMT\") is None\n\n    # Invalid time\n    assert parse_func(\"Tue, 1 Jan 1970 77:88:99 GMT\") is None\n\n\ndef test_domain_matching() -> None:\n    test_func = CookieJar._is_domain_match\n\n    assert test_func(\"test.com\", \"test.com\")\n    assert test_func(\"test.com\", \"sub.test.com\")\n\n    assert not test_func(\"test.com\", \"\")\n    assert not test_func(\"test.com\", \"test.org\")\n    assert not test_func(\"diff-test.com\", \"test.com\")\n    assert not test_func(\"test.com\", \"diff-test.com\")\n    assert not test_func(\"test.com\", \"127.0.0.1\")\n\n\nasync def test_constructor(loop, cookies_to_send, cookies_to_receive) -> None:\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(cookies_to_send)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send\n    assert jar_cookies == expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_constructor_with_expired(\n    loop, cookies_to_send_with_expired, cookies_to_receive\n) -> None:\n    jar = CookieJar()\n    jar.update_cookies(cookies_to_send_with_expired)\n    jar_cookies = SimpleCookie()\n    for cookie in jar:\n        dict.__setitem__(jar_cookies, cookie.key, cookie)\n    expected_cookies = cookies_to_send_with_expired\n    assert jar_cookies != expected_cookies\n    assert jar._loop is loop\n\n\nasync def test_save_load(tmp_path, loop, cookies_to_send, cookies_to_receive) -> None:\n    file_path = pathlib.Path(str(tmp_path)) / \"aiohttp.test.cookie\"\n\n    # export cookie jar\n    jar_save = CookieJar(loop=loop)\n    jar_save.update_cookies(cookies_to_receive)\n    jar_save.save(file_path=file_path)\n\n    jar_load = CookieJar(loop=loop)\n    jar_load.load(file_path=file_path)\n\n    jar_test = SimpleCookie()\n    for cookie in jar_load:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == cookies_to_receive\n\n\nasync def test_update_cookie_with_unicode_domain(loop) -> None:\n    cookies = (\n        \"idna-domain-first=first; Domain=xn--9caa.com; Path=/;\",\n        \"idna-domain-second=second; Domain=xn--9caa.com; Path=/;\",\n    )\n\n    jar = CookieJar(loop=loop)\n    jar.update_cookies(SimpleCookie(cookies[0]), URL(\"http://éé.com/\"))\n    jar.update_cookies(SimpleCookie(cookies[1]), URL(\"http://xn--9caa.com/\"))\n\n    jar_test = SimpleCookie()\n    for cookie in jar:\n        jar_test[cookie.key] = cookie\n\n    assert jar_test == SimpleCookie(\" \".join(cookies))\n\n\nasync def test_filter_cookie_with_unicode_domain(loop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(\n        SimpleCookie(\"idna-domain-first=first; Domain=xn--9caa.com; Path=/; \")\n    )\n    assert len(jar.filter_cookies(URL(\"http://éé.com\"))) == 1\n    assert len(jar.filter_cookies(URL(\"http://xn--9caa.com\"))) == 1\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"expected_cookies\"),\n    (\n        (\n            \"http://pathtest.com/one/two/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/one/two/three/\",\n            (\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"shared-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            ),\n        ),\n        (\n            \"http://test1.example.com/\",\n            (\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            ),\n        ),\n        (\n            \"http://pathtest.com/\",\n            (\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n            ),\n        ),\n    ),\n)\nasync def test_filter_cookies_with_domain_path_lookup_multilevelpath(\n    loop,\n    url,\n    expected_cookies,\n) -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n    jar.update_cookies(cookies)\n    cookies = jar.filter_cookies(URL(url))\n\n    assert len(cookies) == len(expected_cookies)\n    for c in cookies:\n        assert c in expected_cookies\n\n\nasync def test_filter_cookies_str_deprecated(loop: asyncio.AbstractEventLoop) -> None:\n    jar = CookieJar()\n    jar.update_cookies(SimpleCookie(\"shared-cookie=first; Domain=example.com;\"))\n    with pytest.warns(DeprecationWarning):\n        jar.filter_cookies(\"http://éé.com\")\n\n\nasync def test_domain_filter_ip_cookie_send() -> None:\n    jar = CookieJar()\n    cookies = SimpleCookie(\n        \"shared-cookie=first; \"\n        \"domain-cookie=second; Domain=example.com; \"\n        \"subdomain1-cookie=third; Domain=test1.example.com; \"\n        \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n        \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n        \"different-domain-cookie=sixth; Domain=different.org; \"\n        \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n        \"no-path-cookie=eighth; Domain=pathtest.com; \"\n        \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n        \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n        \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n        \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n        \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n        \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n        \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n        \" Max-Age=60; \"\n        \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n        \" Max-Age=string; \"\n        \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n        \" Expires=string;\"\n    )\n\n    jar.update_cookies(cookies)\n    cookies_sent = jar.filter_cookies(URL(\"http://1.2.3.4/\")).output(header=\"Cookie:\")\n    assert cookies_sent == \"Cookie: shared-cookie=first\"\n\n\nasync def test_domain_filter_ip_cookie_receive(cookies_to_receive) -> None:\n    jar = CookieJar()\n\n    jar.update_cookies(cookies_to_receive, URL(\"http://1.2.3.4/\"))\n    assert len(jar) == 0\n\n\n@pytest.mark.parametrize(\n    (\"cookies\", \"expected\", \"quote_bool\"),\n    [\n        (\n            \"shared-cookie=first; ip-cookie=second; Domain=127.0.0.1;\",\n            \"Cookie: ip-cookie=second\\r\\nCookie: shared-cookie=first\",\n            True,\n        ),\n        ('ip-cookie=\"second\"; Domain=127.0.0.1;', 'Cookie: ip-cookie=\"second\"', True),\n        (\"custom-cookie=value/one;\", 'Cookie: custom-cookie=\"value/one\"', True),\n        (\"custom-cookie=value1;\", \"Cookie: custom-cookie=value1\", True),\n        (\"custom-cookie=value/one;\", \"Cookie: custom-cookie=value/one\", False),\n    ],\n    ids=(\n        \"IP domain preserved\",\n        \"no shared cookie\",\n        \"quoted cookie with special char\",\n        \"quoted cookie w/o special char\",\n        \"unquoted cookie with special char\",\n    ),\n)\nasync def test_quotes_correctly_based_on_input(\n    loop, cookies, expected, quote_bool\n) -> None:\n    jar = CookieJar(unsafe=True, quote_cookie=quote_bool)\n    jar.update_cookies(SimpleCookie(cookies))\n    cookies_sent = jar.filter_cookies(URL(\"http://127.0.0.1/\")).output(header=\"Cookie:\")\n    assert cookies_sent == expected\n\n\nasync def test_ignore_domain_ending_with_dot(loop) -> None:\n    jar = CookieJar(loop=loop, unsafe=True)\n    jar.update_cookies(\n        SimpleCookie(\"cookie=val; Domain=example.com.;\"), URL(\"http://www.example.com\")\n    )\n    cookies_sent = jar.filter_cookies(URL(\"http://www.example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"Cookie: cookie=val\"\n    cookies_sent = jar.filter_cookies(URL(\"http://example.com/\"))\n    assert cookies_sent.output(header=\"Cookie:\") == \"\"\n\n\nclass TestCookieJarBase(unittest.TestCase):\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n        # N.B. those need to be overridden in child test cases\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def tearDown(self):\n        self.loop.close()\n\n    def request_reply_with_same_url(self, url):\n        self.jar.update_cookies(self.cookies_to_send)\n        cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        self.jar.update_cookies(self.cookies_to_receive, URL(url))\n        cookies_received = SimpleCookie()\n        for cookie in self.jar:\n            dict.__setitem__(cookies_received, cookie.key, cookie)\n\n        self.jar.clear()\n\n        return cookies_sent, cookies_received\n\n\nclass TestCookieJarSafe(TestCookieJarBase):\n    def setUp(self):\n        super().setUp()\n\n        self.cookies_to_send = SimpleCookie(\n            \"shared-cookie=first; \"\n            \"domain-cookie=second; Domain=example.com; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; \"\n            \"different-domain-cookie=sixth; Domain=different.org; \"\n            \"secure-cookie=seventh; Domain=secure.com; Secure; \"\n            \"no-path-cookie=eighth; Domain=pathtest.com; \"\n            \"path1-cookie=ninth; Domain=pathtest.com; Path=/; \"\n            \"path2-cookie=tenth; Domain=pathtest.com; Path=/one; \"\n            \"path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; \"\n            \"path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; \"\n            \"expires-cookie=thirteenth; Domain=expirestest.com; Path=/;\"\n            \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \"\n            \"max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;\"\n            \" Max-Age=60; \"\n            \"invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; \"\n            \" Max-Age=string; \"\n            \"invalid-expires-cookie=sixteenth; Domain=invalid-values.com; \"\n            \" Expires=string;\"\n        )\n\n        self.cookies_to_receive = SimpleCookie(\n            \"unconstrained-cookie=first; Path=/; \"\n            \"domain-cookie=second; Domain=example.com; Path=/; \"\n            \"subdomain1-cookie=third; Domain=test1.example.com; Path=/; \"\n            \"subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; \"\n            \"dotted-domain-cookie=fifth; Domain=.example.com; Path=/; \"\n            \"different-domain-cookie=sixth; Domain=different.org; Path=/; \"\n            \"no-path-cookie=seventh; Domain=pathtest.com; \"\n            \"path-cookie=eighth; Domain=pathtest.com; Path=/somepath; \"\n            \"wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;\"\n        )\n\n        async def make_jar():\n            return CookieJar()\n\n        self.jar = self.loop.run_until_complete(make_jar())\n\n    def timed_request(self, url, update_time, send_time):\n        if isinstance(update_time, int):\n            update_time = datetime.timedelta(seconds=update_time)\n        elif isinstance(update_time, float):\n            update_time = datetime.datetime.fromtimestamp(update_time)\n        if isinstance(send_time, int):\n            send_time = datetime.timedelta(seconds=send_time)\n        elif isinstance(send_time, float):\n            send_time = datetime.datetime.fromtimestamp(send_time)\n\n        with freeze_time(update_time):\n            self.jar.update_cookies(self.cookies_to_send)\n\n        with freeze_time(send_time):\n            cookies_sent = self.jar.filter_cookies(URL(url))\n\n        self.jar.clear()\n\n        return cookies_sent\n\n    def test_domain_filter_same_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_same_host_and_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://test1.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"domain-cookie\",\n                \"subdomain1-cookie\",\n                \"dotted-domain-cookie\",\n            },\n        )\n\n    def test_domain_filter_same_host_diff_subdomain(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.example.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"domain-cookie\", \"dotted-domain-cookie\"},\n        )\n\n    def test_domain_filter_diff_host(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://different.org/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()), {\"shared-cookie\", \"different-domain-cookie\"}\n        )\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\"unconstrained-cookie\", \"different-domain-cookie\"},\n        )\n\n    def test_domain_filter_host_only(self) -> None:\n        self.jar.update_cookies(self.cookies_to_receive, URL(\"http://example.com/\"))\n        sub_cookie = SimpleCookie(\"subdomain=spam; Path=/;\")\n        self.jar.update_cookies(sub_cookie, URL(\"http://foo.example.com/\"))\n\n        cookies_sent = self.jar.filter_cookies(URL(\"http://foo.example.com/\"))\n        self.assertIn(\"subdomain\", set(cookies_sent.keys()))\n        self.assertNotIn(\"unconstrained-cookie\", set(cookies_sent.keys()))\n\n    def test_secure_filter(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"https://secure.com/\")\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"secure-cookie\"})\n\n    def test_path_filter_root(self) -> None:\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_filter_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\"http://pathtest.com/one/\")\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\", \"path2-cookie\"},\n        )\n\n    def test_path_filter_file(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n            },\n        )\n\n    def test_path_filter_subfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_subsubfolder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/one/two/three/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\n                \"shared-cookie\",\n                \"no-path-cookie\",\n                \"path1-cookie\",\n                \"path2-cookie\",\n                \"path3-cookie\",\n                \"path4-cookie\",\n            },\n        )\n\n    def test_path_filter_different_folder(self) -> None:\n\n        cookies_sent, _ = self.request_reply_with_same_url(\n            \"http://pathtest.com/hundred/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"no-path-cookie\", \"path1-cookie\"},\n        )\n\n    def test_path_value(self) -> None:\n        _, cookies_received = self.request_reply_with_same_url(\"http://pathtest.com/\")\n\n        self.assertEqual(\n            set(cookies_received.keys()),\n            {\n                \"unconstrained-cookie\",\n                \"no-path-cookie\",\n                \"path-cookie\",\n                \"wrong-path-cookie\",\n            },\n        )\n\n        self.assertEqual(cookies_received[\"no-path-cookie\"][\"path\"], \"/\")\n        self.assertEqual(cookies_received[\"path-cookie\"][\"path\"], \"/somepath\")\n        self.assertEqual(cookies_received[\"wrong-path-cookie\"][\"path\"], \"/\")\n\n    def test_expires(self) -> None:\n        ts_before = datetime.datetime(\n            1975, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        ts_after = datetime.datetime(\n            2030, 1, 1, tzinfo=datetime.timezone.utc\n        ).timestamp()\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_before\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"expires-cookie\"})\n\n        cookies_sent = self.timed_request(\n            \"http://expirestest.com/\", ts_before, ts_after\n        )\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_max_age(self) -> None:\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 1000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\", \"max-age-cookie\"})\n\n        cookies_sent = self.timed_request(\"http://maxagetest.com/\", 1000, 2000)\n\n        self.assertEqual(set(cookies_sent.keys()), {\"shared-cookie\"})\n\n    def test_invalid_values(self) -> None:\n        cookies_sent, cookies_received = self.request_reply_with_same_url(\n            \"http://invalid-values.com/\"\n        )\n\n        self.assertEqual(\n            set(cookies_sent.keys()),\n            {\"shared-cookie\", \"invalid-max-age-cookie\", \"invalid-expires-cookie\"},\n        )\n\n        cookie = cookies_sent[\"invalid-max-age-cookie\"]\n        self.assertEqual(cookie[\"max-age\"], \"\")\n\n        cookie = cookies_sent[\"invalid-expires-cookie\"]\n        self.assertEqual(cookie[\"expires\"], \"\")\n\n    def test_cookie_not_expired_when_added_after_removal(self) -> None:\n        # Test case for https://github.com/aio-libs/aiohttp/issues/2084\n        timestamps = [\n            533588.993,\n            533588.993,\n            533588.993,\n            533588.993,\n            533589.093,\n            533589.093,\n        ]\n\n        loop = mock.Mock()\n        loop.time.side_effect = itertools.chain(\n            timestamps, itertools.cycle([timestamps[-1]])\n        )\n\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        # Remove `foo` cookie.\n        jar.update_cookies(SimpleCookie('foo=\"\"; Max-Age=0'))\n        # Set `foo` cookie to `bar`.\n        jar.update_cookies(SimpleCookie('foo=\"bar\"'))\n\n        # Assert that there is a cookie.\n        assert len(jar) == 1\n\n    def test_path_filter_diff_folder_same_name(self) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        self.assertEqual(len(jar), 2)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n    def test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order(\n        self,\n    ) -> None:\n        async def make_jar():\n            return CookieJar(unsafe=True)\n\n        jar = self.loop.run_until_complete(make_jar())\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=one; Domain=pathtest.com; Path=/one; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=zero; Domain=pathtest.com; Path=/; \")\n        )\n        jar.update_cookies(\n            SimpleCookie(\"path-cookie=two; Domain=pathtest.com; Path=/second; \")\n        )\n        self.assertEqual(len(jar), 3)\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"zero\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/second\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"two\")\n\n        jar_filtered = jar.filter_cookies(URL(\"http://pathtest.com/one\"))\n        self.assertEqual(len(jar_filtered), 1)\n        self.assertEqual(jar_filtered[\"path-cookie\"].value, \"one\")\n\n\nasync def test_dummy_cookie_jar() -> None:\n    cookie = SimpleCookie(\"foo=bar; Domain=example.com;\")\n    dummy_jar = DummyCookieJar()\n    assert len(dummy_jar) == 0\n    dummy_jar.update_cookies(cookie)\n    assert len(dummy_jar) == 0\n    with pytest.raises(StopIteration):\n        next(iter(dummy_jar))\n    assert not dummy_jar.filter_cookies(URL(\"http://example.com/\"))\n    dummy_jar.clear()\n\n\nasync def test_loose_cookies_types() -> None:\n    jar = CookieJar()\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", Morsel())],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": Morsel()},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        jar.update_cookies(cookies=loose_cookies_type)\n\n\nasync def test_cookie_jar_clear_all():\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    sut.update_cookies(cookie)\n\n    sut.clear()\n    assert len(sut) == 0\n\n\nasync def test_cookie_jar_clear_expired():\n    sut = CookieJar()\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        sut.update_cookies(cookie)\n\n    for _ in range(2):\n        sut.clear(not_)\n        with freeze_time(\"1980-01-01\"):\n            assert len(sut) == 0\n\n\nasync def test_cookie_jar_expired_changes() -> None:\n    \"\"\"Test that expire time changes are handled as expected.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_noon = SimpleCookie()\n    cookie_noon[\"foo\"] = \"bar\"\n    cookie_noon[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    cookie_one_pm = SimpleCookie()\n    cookie_one_pm[\"foo\"] = \"bar\"\n    cookie_one_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 13:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n        jar.update_cookies(cookie_noon)\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_eleven_am)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_one_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 13:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        freezer.move_to(\"1990-01-01 14:00:00+00:00\")\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n\n\nasync def test_cookie_jar_duplicates_with_expire_heap() -> None:\n    \"\"\"Test that duplicate cookies do not grow the expires heap.\"\"\"\n    jar = CookieJar()\n\n    cookie_eleven_am = SimpleCookie()\n    cookie_eleven_am[\"foo\"] = \"bar\"\n    cookie_eleven_am[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 11:00:00 GMT\"\n\n    cookie_two_pm = SimpleCookie()\n    cookie_two_pm[\"foo\"] = \"bar\"\n    cookie_two_pm[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 10:00:00+00:00\")\n\n        for _ in range(10):\n            jar.update_cookies(cookie_eleven_am)\n\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n\n        assert len(jar._expire_heap) == 1\n\n        freezer.move_to(\"1990-01-01 16:00:00+00:00\")\n        jar.update_cookies(cookie_two_pm)\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 0\n        assert len(jar._expire_heap) == 0\n\n\nasync def test_cookie_jar_filter_cookies_expires() -> None:\n    \"\"\"Test that calling filter_cookies will expire stale cookies.\"\"\"\n    jar = CookieJar()\n    assert len(jar) == 0\n\n    cookie = SimpleCookie()\n\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 12:00:00 GMT\"\n\n    with freeze_time(\"1980-01-01\"):\n        jar.update_cookies(cookie)\n\n    assert len(jar) == 1\n\n    # filter_cookies should expire stale cookies\n    jar.filter_cookies(URL(\"http://any.com/\"))\n\n    assert len(jar) == 0\n\n\nasync def test_cookie_jar_heap_cleanup() -> None:\n    \"\"\"Test that the heap gets cleaned up when there are many old expirations.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        start_time = datetime.datetime(\n            1990, 1, 1, 10, 0, 0, tzinfo=datetime.timezone.utc\n        )\n        for i in range(min_cookies_to_cleanup):\n            cookie = SimpleCookie()\n            cookie[\"foo\"] = \"bar\"\n            cookie[\"foo\"][\"expires\"] = (\n                start_time + datetime.timedelta(seconds=i)\n            ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n            jar.update_cookies(cookie)\n            assert len(jar._expire_heap) == i + 1\n\n        assert len(jar._expire_heap) == min_cookies_to_cleanup\n\n        # Now that we reached the minimum number of cookies to cleanup,\n        # add one more cookie to trigger the cleanup\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"expires\"] = (\n            start_time + datetime.timedelta(seconds=i + 1)\n        ).strftime(\"%a, %d %b %Y %H:%M:%S GMT\")\n        jar.update_cookies(cookie)\n\n        # Verify that the heap has been cleaned up\n        assert len(jar) == 1\n        matched_cookies = jar.filter_cookies(URL(\"/\"))\n        assert len(matched_cookies) == 1\n        assert \"foo\" in matched_cookies\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 1\n\n\nasync def test_cookie_jar_heap_maintains_order_after_cleanup() -> None:\n    \"\"\"Test that order is maintained after cleanup.\"\"\"\n    jar = CookieJar()\n    # The heap should not be cleaned up when there are less than 100 expiration changes\n    min_cookies_to_cleanup = 100\n\n    with freeze_time() as freezer:\n        freezer.move_to(\"1990-01-01 09:00:00+00:00\")\n\n        for hour in (12, 13):\n            for i in range(min_cookies_to_cleanup):\n                cookie = SimpleCookie()\n                cookie[\"foo\"] = \"bar\"\n                cookie[\"foo\"][\"domain\"] = f\"example{i}.com\"\n                cookie[\"foo\"][\"expires\"] = f\"Tue, 1 Jan 1990 {hour}:00:00 GMT\"\n                jar.update_cookies(cookie)\n\n        # Get the jar into a state where the next cookie will trigger the cleanup\n        assert len(jar._expire_heap) == min_cookies_to_cleanup * 2\n        assert len(jar._expirations) == min_cookies_to_cleanup\n\n        cookie = SimpleCookie()\n        cookie[\"foo\"] = \"bar\"\n        cookie[\"foo\"][\"domain\"] = \"example0.com\"\n        cookie[\"foo\"][\"expires\"] = \"Tue, 1 Jan 1990 14:00:00 GMT\"\n        jar.update_cookies(cookie)\n\n        assert len(jar) == 100\n        # The heap should have been cleaned up\n        assert len(jar._expire_heap) == 100\n\n        # Verify that the heap is still ordered\n        heap_before = jar._expire_heap.copy()\n        heapq.heapify(jar._expire_heap)\n        assert heap_before == jar._expire_heap\n\n\nasync def test_cookie_jar_clear_domain() -> None:\n    sut = CookieJar()\n    cookie = SimpleCookie()\n    cookie[\"foo\"] = \"bar\"\n    cookie[\"domain_cookie\"] = \"value\"\n    cookie[\"domain_cookie\"][\"domain\"] = \"example.com\"\n    cookie[\"subdomain_cookie\"] = \"value\"\n    cookie[\"subdomain_cookie\"][\"domain\"] = \"test.example.com\"\n    sut.update_cookies(cookie)\n\n    sut.clear_domain(\"example.com\")\n    iterator = iter(sut)\n    morsel = next(iterator)\n    assert morsel.key == \"foo\"\n    assert morsel.value == \"bar\"\n    with pytest.raises(StopIteration):\n        next(iterator)\n\n\nasync def test_pickle_format(cookies_to_send) -> None:\n    \"\"\"Test if cookiejar pickle format breaks.\n\n    If this test fails, it may indicate that saved cookiejars will stop working.\n    If that happens then:\n        1. Avoid releasing the change in a bugfix release.\n        2. Try to include a migration script in the release notes (example below).\n        3. Use dump_cookiejar() at the top of this file to update `pickled`.\n\n    Depending on the changes made, a migration script might look like:\n        import pickle\n        with file_path.open(\"rb\") as f:\n            cookies = pickle.load(f)\n\n        morsels = [(name, m) for c in cookies.values() for name, m in c.items()]\n        cookies.clear()\n        for name, m in morsels:\n            cookies[(m[\"domain\"], m[\"path\"])][name] = m\n\n        with file_path.open(\"wb\") as f:\n            pickle.dump(cookies, f, pickle.HIGHEST_PROTOCOL)\n    \"\"\"\n    pickled = b\"\\x80\\x04\\x95\\xc8\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x8c\\x0bcollections\\x94\\x8c\\x0bdefaultdict\\x94\\x93\\x94\\x8c\\x0chttp.cookies\\x94\\x8c\\x0cSimpleCookie\\x94\\x93\\x94\\x85\\x94R\\x94(\\x8c\\x00\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rshared-cookie\\x94h\\x03\\x8c\\x06Morsel\\x94\\x93\\x94)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\x01/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x08\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(\\x8c\\x03key\\x94h\\x0b\\x8c\\x05value\\x94\\x8c\\x05first\\x94\\x8c\\x0bcoded_value\\x94h\\x1cubs\\x8c\\x0bexample.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\rdomain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x1e\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah!h\\x1b\\x8c\\x06second\\x94h\\x1dh-ub\\x8c\\x14dotted-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0bexample.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah.h\\x1b\\x8c\\x05fifth\\x94h\\x1dh;ubu\\x8c\\x11test1.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h<\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah?h\\x1b\\x8c\\x05third\\x94h\\x1dhKubs\\x8c\\x11test2.example.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x11subdomain2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hL\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahOh\\x1b\\x8c\\x06fourth\\x94h\\x1dh[ubs\\x8c\\rdifferent.org\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x17different-domain-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\\\\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah_h\\x1b\\x8c\\x05sixth\\x94h\\x1dhkubs\\x8c\\nsecure.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\rsecure-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94hl\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94\\x88\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ahoh\\x1b\\x8c\\x07seventh\\x94h\\x1dh{ubs\\x8c\\x0cpathtest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0eno-path-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h|\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x7fh\\x1b\\x8c\\x06eighth\\x94h\\x1dh\\x8bub\\x8c\\x0cpath1-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x8ch\\x1b\\x8c\\x05ninth\\x94h\\x1dh\\x99ubu\\x8c\\x0cpathtest.com\\x94\\x8c\\x04/one\\x94\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0cpath2-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x9b\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\x9a\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\x9eh\\x1b\\x8c\\x05tenth\\x94h\\x1dh\\xaaubs\\x8c\\x0cpathtest.com\\x94\\x8c\\x08/one/two\\x94\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x0cpath3-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\xac\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xab\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xafh\\x1b\\x8c\\x08eleventh\\x94h\\x1dh\\xbbub\\x8c\\x0cpath4-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94\\x8c\\t/one/two/\\x94\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x0cpathtest.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xbch\\x1b\\x8c\\x07twelfth\\x94h\\x1dh\\xcaubu\\x8c\\x0fexpirestest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0eexpires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94\\x8c\\x1cTue, 1 Jan 2999 12:00:00 GMT\\x94\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xcb\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xceh\\x1b\\x8c\\nthirteenth\\x94h\\x1dh\\xdbubs\\x8c\\x0emaxagetest.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94\\x8c\\x0emax-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xdc\\x8c\\x07max-age\\x94\\x8c\\x0260\\x94\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xdfh\\x1b\\x8c\\nfourteenth\\x94h\\x1dh\\xecubs\\x8c\\x12invalid-values.com\\x94h\\x08\\x86\\x94h\\x05)\\x81\\x94(\\x8c\\x16invalid-max-age-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94h\\xed\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xf0h\\x1b\\x8c\\tfifteenth\\x94h\\x1dh\\xfcub\\x8c\\x16invalid-expires-cookie\\x94h\\r)\\x81\\x94(\\x8c\\x07expires\\x94h\\x08\\x8c\\x04path\\x94h\\x11\\x8c\\x07comment\\x94h\\x08\\x8c\\x06domain\\x94\\x8c\\x12invalid-values.com\\x94\\x8c\\x07max-age\\x94h\\x08\\x8c\\x06secure\\x94h\\x08\\x8c\\x08httponly\\x94h\\x08\\x8c\\x07version\\x94h\\x08\\x8c\\x08samesite\\x94h\\x08u}\\x94(h\\x1ah\\xfdh\\x1b\\x8c\\tsixteenth\\x94h\\x1dj\\n\\x01\\x00\\x00ubuu.\"\n    cookies = pickle.loads(pickled)\n\n    cj = CookieJar()\n    cj.update_cookies(cookies_to_send)\n\n    assert cookies == cj._cookies\n\n\n@pytest.mark.parametrize(\n    \"url\",\n    [\n        \"http://127.0.0.1/index.html\",\n        URL(\"http://127.0.0.1/index.html\"),\n        [\"http://127.0.0.1/index.html\"],\n        [URL(\"http://127.0.0.1/index.html\")],\n    ],\n)\nasync def test_treat_as_secure_origin_init(url) -> None:\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=url)\n    assert jar._treat_as_secure_origin == [URL(\"http://127.0.0.1\")]\n\n\nasync def test_treat_as_secure_origin() -> None:\n    endpoint = URL(\"http://127.0.0.1/\")\n\n    jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint])\n    secure_cookie = SimpleCookie(\n        \"cookie-key=cookie-value; HttpOnly; Path=/; Secure\",\n    )\n\n    jar.update_cookies(\n        secure_cookie,\n        endpoint,\n    )\n\n    assert len(jar) == 1\n    filtered_cookies = jar.filter_cookies(request_url=endpoint)\n    assert len(filtered_cookies) == 1\n",
        "import asyncio\nimport base64\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha1, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom typing import Any\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.http import WS_KEY\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef create_mocked_conn(loop: Any):\n    def _proto_factory(conn_closing_result=None, **kwargs):\n        proto = mock.create_autospec(ResponseHandler, **kwargs)\n        proto.closed = loop.create_future()\n        proto.closed.set_result(conn_closing_result)\n        return proto\n\n    yield _proto_factory\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n\n\n@pytest.fixture\ndef start_connection():\n    with mock.patch(\n        \"aiohttp.connector.aiohappyeyeballs.start_connection\",\n        autospec=True,\n        spec_set=True,\n    ) as start_connection_mock:\n        yield start_connection_mock\n\n\n@pytest.fixture\ndef key_data():\n    return os.urandom(16)\n\n\n@pytest.fixture\ndef key(key_data: Any):\n    return base64.b64encode(key_data)\n\n\n@pytest.fixture\ndef ws_key(key: Any):\n    return base64.b64encode(sha1(key + WS_KEY).digest()).decode()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_find_header.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/mask.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/mask.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/reader_c.pxd\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket/mask.c aiohttp/_websocket/mask.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 6s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/worker.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/models.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/reader.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/reader_c.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/reader_py.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/aiohttp/_websocket/writer.py\nuv pip install -e . -c requirements/runtime-deps.txt\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 1ms\nPrepared 1 package in 0.20ms\nInstalled 1 package in 15ms\n + pip==24.3.1\nResolved 3 packages in 11ms\nInstalled 3 packages in 12ms\n + cython==3.0.11\n + multidict==6.1.0\n + typing-extensions==4.12.2\nResolved 97 packages in 111ms\nInstalled 94 packages in 63ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.4.3\n + aiohttp-theme==0.1.7\n + aiosignal==1.3.1\n + alabaster==0.7.13\n + annotated-types==0.7.0\n + async-timeout==4.0.3\n + attrs==24.2.0\n + babel==2.16.0\n + brotli==1.1.0\n + build==1.2.2.post1\n + certifi==2024.8.30\n + cffi==1.17.1\n + cfgv==3.4.0\n + charset-normalizer==3.4.0\n + cherry-picker==2.2.0\n + click==8.1.7\n + coverage==7.6.1\n + cryptography==43.0.3\n + distlib==0.3.9\n + docutils==0.20.1\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + freezegun==1.5.1\n + frozenlist==1.5.0\n + gidgethub==5.3.0\n + gunicorn==23.0.0\n + identify==2.6.1\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.5.0\n + importlib-resources==6.4.5\n + incremental==24.7.2\n + iniconfig==2.0.0\n + jinja2==3.1.4\n + markdown-it-py==3.0.0\n + markupsafe==2.1.5\n + mdurl==0.1.2\n + mypy==1.11.2\n + mypy-extensions==1.0.0\n + nodeenv==1.9.1\n + packaging==24.1\n + pip-tools==7.4.1\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pre-commit==3.5.0\n + propcache==0.2.0\n + proxy-py==2.4.9\n + pycares==4.4.0\n + pycparser==2.22\n + pydantic==2.9.2\n + pydantic-core==2.23.4\n + pygments==2.18.0\n + pyjwt==2.8.0\n + pyproject-hooks==1.2.0\n + pytest==8.3.3\n + pytest-codspeed==3.0.0\n + pytest-cov==5.0.0\n + pytest-mock==3.14.0\n + python-dateutil==2.9.0.post0\n + python-on-whales==0.73.0\n + pyyaml==6.0.2\n + re-assert==1.1.0\n + regex==2024.9.11\n + requests==2.32.3\n + rich==13.9.3\n + setuptools==75.2.0\n + setuptools-git==1.2\n + shellingham==1.5.4\n + six==1.16.0\n + slotscheck==0.19.1\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.2\n + towncrier==23.11.0\n + tqdm==4.66.5\n + trustme==1.1.0\n + typer==0.12.5\n + uritemplate==4.1.1\n + urllib3==2.2.3\n + uvloop==0.21.0\n + valkey==6.0.2\n + virtualenv==20.27.0\n + wait-for-it==2.2.2\n + wheel==0.44.0\n + yarl==1.17.1\n + zipp==3.20.2\nResolved 11 packages in 1.68s\n  × Failed to build `aiohttp @ file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71`\n  ├─▶ The build backend returned an error\n  ╰─▶ Call to `setuptools.build_meta.build_editable` failed (exit status: 1)\n\n      [stdout]\n      running editable_wheel\n      creating /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info\n      writing /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/PKG-INFO\n      writing dependency_links to /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/dependency_links.txt\n      writing requirements to /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/requires.txt\n      writing top-level names to /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/top_level.txt\n      writing manifest file '/home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/SOURCES.txt'\n      reading manifest file '/home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/SOURCES.txt'\n      reading manifest template 'MANIFEST.in'\n      adding license file 'LICENSE.txt'\n      writing manifest file '/home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp.egg-info/SOURCES.txt'\n      creating '/home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp-3.11.0b3.dist-info'\n      creating /home/gcpuser/.cache/uv/builds-v0/.tmprQzGSO/.tmp-t6u4mdsc/aiohttp-3.11.0b3.dist-info/WHEEL\n      running build_py\n      running build_ext\n      building 'aiohttp._websocket.mask' extension\n      creating /tmp/tmprlhd_ike.build-temp/aiohttp/_websocket\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      aiohttp/_websocket/mask.c -o /tmp/tmprlhd_ike.build-temp/aiohttp/_websocket/mask.o\n      creating /tmp/tmpe174p0k2.build-lib/aiohttp/_websocket\n      cc -pthread -shared -Wl,--exclude-libs,ALL /tmp/tmprlhd_ike.build-temp/aiohttp/_websocket/mask.o\n      -L/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib -o /tmp/tmpe174p0k2.build-lib/aiohttp/_websocket/mask.cpython-39-x86_64-linux-gnu.so\n      building 'aiohttp._http_parser' extension\n      creating /tmp/tmprlhd_ike.build-temp/vendor/llhttp/build/c\n      creating /tmp/tmprlhd_ike.build-temp/vendor/llhttp/src/native\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -DLLHTTP_STRICT_MODE=0 -Ivendor/llhttp/build\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      aiohttp/_find_header.c -o /tmp/tmprlhd_ike.build-temp/aiohttp/_find_header.o\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -DLLHTTP_STRICT_MODE=0 -Ivendor/llhttp/build\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      aiohttp/_http_parser.c -o /tmp/tmprlhd_ike.build-temp/aiohttp/_http_parser.o\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -DLLHTTP_STRICT_MODE=0 -Ivendor/llhttp/build\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      vendor/llhttp/build/c/llhttp.c -o /tmp/tmprlhd_ike.build-temp/vendor/llhttp/build/c/llhttp.o\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -DLLHTTP_STRICT_MODE=0 -Ivendor/llhttp/build\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      vendor/llhttp/src/native/api.c -o /tmp/tmprlhd_ike.build-temp/vendor/llhttp/src/native/api.o\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -DLLHTTP_STRICT_MODE=0 -Ivendor/llhttp/build\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      vendor/llhttp/src/native/http.c -o /tmp/tmprlhd_ike.build-temp/vendor/llhttp/src/native/http.o\n      cc -pthread -shared -Wl,--exclude-libs,ALL /tmp/tmprlhd_ike.build-temp/aiohttp/_find_header.o /tmp/tmprlhd_ike.build-temp/aiohttp/_http_parser.o\n      /tmp/tmprlhd_ike.build-temp/vendor/llhttp/build/c/llhttp.o /tmp/tmprlhd_ike.build-temp/vendor/llhttp/src/native/api.o\n      /tmp/tmprlhd_ike.build-temp/vendor/llhttp/src/native/http.o -L/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib -o\n      /tmp/tmpe174p0k2.build-lib/aiohttp/_http_parser.cpython-39-x86_64-linux-gnu.so\n      building 'aiohttp._http_writer' extension\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      aiohttp/_http_writer.c -o /tmp/tmprlhd_ike.build-temp/aiohttp/_http_writer.o\n      cc -pthread -shared -Wl,--exclude-libs,ALL /tmp/tmprlhd_ike.build-temp/aiohttp/_http_writer.o\n      -L/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib -o /tmp/tmpe174p0k2.build-lib/aiohttp/_http_writer.cpython-39-x86_64-linux-gnu.so\n      building 'aiohttp._websocket.reader_c' extension\n      cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC\n      -I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include -I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9 -c\n      aiohttp/_websocket/reader_c.c -o /tmp/tmprlhd_ike.build-temp/aiohttp/_websocket/reader_c.o\n\n      [stderr]\n      *********************\n      * Accelerated build *\n      *********************\n      warning: no files found matching 'aiohttp' anywhere in distribution\n      warning: no previously-included files matching '*.pyd' found anywhere in distribution\n      warning: no previously-included files matching '*.so' found anywhere in distribution\n      warning: no previously-included files matching '*.lib' found anywhere in distribution\n      warning: no previously-included files matching '*.dll' found anywhere in distribution\n      warning: no previously-included files matching '*.a' found anywhere in distribution\n      warning: no previously-included files matching '*.obj' found anywhere in distribution\n      warning: no previously-included files found matching 'aiohttp/*.html'\n      no previously-included directories found matching 'docs/_build'\n      aiohttp/_find_header.c: In function ‘find_header’:\n      aiohttp/_find_header.c:21:19: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]\n         21 |     char *pchar = str;\n            |                   ^~~\n      aiohttp/_find_header.c:9867:1: warning: label ‘missing’ defined but not used [-Wunused-label]\n       9867 | missing:\n            | ^~~~~~~\n      aiohttp/_http_parser.c: In function ‘__pyx_f_7aiohttp_12_http_parser_cb_on_header_field’:\n      aiohttp/_http_parser.c:16286:33: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long\n      unsigned int’} [-Wsign-compare]\n      16286 |       __pyx_t_6 = (__pyx_v_size > __pyx_v_pyparser->_max_field_size);\n            |                                 ^\n      aiohttp/_http_parser.c:16354:148: warning: passing argument 2 of ‘__pyx_v_pyparser->__pyx_vtab->_on_header_field’ discards ‘const’ qualifier from pointer\n      target type [-Wdiscarded-qualifiers]\n      16354 |       __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_field(__pyx_v_pyparser,\n      __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 723, __pyx_L3_error)\n            |                                                                                                                                                    ^~~~~~~~~~\n      aiohttp/_http_parser.c:16354:148: note: expected ‘char *’ but argument is of type ‘const char *’\n      aiohttp/_http_parser.c: In function ‘__pyx_f_7aiohttp_12_http_parser_cb_on_header_value’:\n      aiohttp/_http_parser.c:16576:33: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long\n      unsigned int’} [-Wsign-compare]\n      16576 |       __pyx_t_6 = (__pyx_v_size > __pyx_v_pyparser->_max_field_size);\n            |                                 ^\n      aiohttp/_http_parser.c:16644:148: warning: passing argument 2 of ‘__pyx_v_pyparser->__pyx_vtab->_on_header_value’ discards ‘const’ qualifier from pointer\n      target type [-Wdiscarded-qualifiers]\n      16644 |       __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_value(__pyx_v_pyparser,\n      __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 740, __pyx_L3_error)\n            |                                                                                                                                                    ^~~~~~~~~~\n      aiohttp/_http_parser.c:16644:148: note: expected ‘char *’ but argument is of type ‘const char *’\n      aiohttp/_http_parser.c: In function ‘__pyx_pw_7aiohttp_12_http_parser_10HttpParser_7feed_data’:\n      aiohttp/_http_parser.c:13135:17: warning: ‘__pyx_v_nb’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n      13135 |     __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_data, __pyx_v_nb, 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 572,\n      __pyx_L1_error)\n            |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n      aiohttp/_http_parser.c:12742:10: note: ‘__pyx_v_nb’ was declared here\n      12742 |   size_t __pyx_v_nb;\n            |          ^~~~~~~~~~\n      cc1: fatal error: aiohttp/_websocket/reader_c.c: No such file or directory\n      compilation terminated.\n      Traceback (most recent call last):\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/spawn.py\", line 70, in spawn\n          subprocess.check_call(cmd, env=_inject_macos_ver(env))\n        File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/subprocess.py\", line 373, in check_call\n          raise CalledProcessError(retcode, cmd)\n      subprocess.CalledProcessError: Command '['/usr/bin/cc', '-pthread', '-Wno-unused-result', '-Wsign-compare', '-Wunreachable-code',\n      '-DNDEBUG', '-g', '-fwrapv', '-O3', '-Wall', '-fPIC', '-fPIC', '-I/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/include',\n      '-I/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/include/python3.9', '-c', 'aiohttp/_websocket/reader_c.c', '-o',\n      '/tmp/tmprlhd_ike.build-temp/aiohttp/_websocket/reader_c.o']' returned non-zero exit status 1.\n\n      The above exception was the direct cause of the following exception:\n\n      Traceback (most recent call last):\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/unixccompiler.py\", line 200, in _compile\n          self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/ccompiler.py\", line 1045, in spawn\n          spawn(cmd, dry_run=self.dry_run, **kwargs)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/spawn.py\", line 76, in spawn\n          raise DistutilsExecError(\n      distutils.errors.DistutilsExecError: command '/usr/bin/cc' failed with exit code 1\n\n      During handling of the above exception, another exception occurred:\n\n      Traceback (most recent call last):\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/editable_wheel.py\", line 139, in run\n          self._create_wheel_file(bdist_wheel)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/editable_wheel.py\", line 340, in _create_wheel_file\n          files, mapping = self._run_build_commands(dist_name, unpacked, lib, tmp)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/editable_wheel.py\", line 263, in _run_build_commands\n          self._run_build_subcommands()\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/editable_wheel.py\", line 290, in _run_build_subcommands\n          self.run_command(name)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/cmd.py\", line 316, in run_command\n          self.distribution.run_command(command)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/dist.py\", line 995, in run_command\n          super().run_command(command)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/dist.py\", line 973, in run_command\n          cmd_obj.run()\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/build_ext.py\", line 99, in run\n          _build_ext.run(self)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/command/build_ext.py\", line 359, in run\n          self.build_extensions()\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/command/build_ext.py\", line 476, in build_extensions\n          self._build_extensions_serial()\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/command/build_ext.py\", line 502, in\n      _build_extensions_serial\n          self.build_extension(ext)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/command/build_ext.py\", line 264, in build_extension\n          _build_ext.build_extension(self, ext)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/command/build_ext.py\", line 557, in build_extension\n          objects = self.compiler.compile(\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/ccompiler.py\", line 606, in compile\n          self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)\n        File \"/home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/unixccompiler.py\", line 202, in _compile\n          raise CompileError(msg)\n      distutils.errors.CompileError: command '/usr/bin/cc' failed with exit code 1\n      /home/gcpuser/.cache/uv/builds-v0/.tmpZvMd1p/lib/python3.9/site-packages/setuptools/_distutils/dist.py:973: _DebuggingTips: Problem in editable installation.\n      !!\n\n              ********************************************************************************\n              An error happened while installing `aiohttp` in editable mode.\n\n              The following steps are recommended to help debug this problem:\n\n              - Try to install the project normally, without using the editable mode.\n                Does the error still persist?\n                (If it does, try fixing the problem before attempting the editable mode).\n              - If you are using binary extensions, make sure you have all OS-level\n                dependencies installed (e.g. compilers, toolchains, binary libraries, ...).\n              - Try the latest version of setuptools (maybe the error was already fixed).\n              - If you (or your project dependencies) are using any setuptools extension\n                or customization, make sure they support the editable mode.\n\n              After following the steps above, if the problem still persists and\n              you think this is related to how setuptools handles editable installations,\n              please submit a reproducible example\n              (see https://stackoverflow.com/help/minimal-reproducible-example) to:\n\n                  https://github.com/pypa/setuptools/issues\n\n              See https://setuptools.pypa.io/en/latest/userguide/development_mode.html for details.\n              ********************************************************************************\n\n      !!\n        cmd_obj.run()\n      error: command '/usr/bin/cc' failed with exit code 1\n\n      hint: This usually indicates a problem with the package or the build environment.\nmake: *** [Makefile:100: .develop] Error 1\nResolved 26 packages in 16ms\nInstalled 5 packages in 5ms\n + async-generator==1.10\n + brotlipy==0.7.0\n + chardet==5.2.0\n + multdict==0.0.5\n + pytest-asyncio==0.25.1\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/.venv/bin/python\ncodspeed: 3.0.0 (disabled, mode: walltime, timer_resolution: 1.0ns)\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1, codspeed-3.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 56 items\n\nr2e_tests/test_1.py::test_date_parsing PASSED                            [  1%]\nr2e_tests/test_1.py::test_domain_matching PASSED                         [  3%]\nr2e_tests/test_1.py::test_constructor[pyloop] PASSED                     [  5%]\nr2e_tests/test_1.py::test_constructor_with_expired[pyloop] PASSED        [  7%]\nr2e_tests/test_1.py::test_save_load[pyloop] PASSED                       [  8%]\nr2e_tests/test_1.py::test_update_cookie_with_unicode_domain[pyloop] PASSED [ 10%]\nr2e_tests/test_1.py::test_filter_cookie_with_unicode_domain[pyloop] PASSED [ 12%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/-expected_cookies0] PASSED [ 14%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two-expected_cookies1] PASSED [ 16%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/three/-expected_cookies2] PASSED [ 17%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://test1.example.com/-expected_cookies3] PASSED [ 19%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/-expected_cookies4] PASSED [ 21%]\nr2e_tests/test_1.py::test_filter_cookies_str_deprecated[pyloop] PASSED   [ 23%]\nr2e_tests/test_1.py::test_domain_filter_ip_cookie_send PASSED            [ 25%]\nr2e_tests/test_1.py::test_domain_filter_ip_cookie_receive PASSED         [ 26%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-IP domain preserved] PASSED [ 28%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-no shared cookie] PASSED [ 30%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie with special char] PASSED [ 32%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie w/o special char] PASSED [ 33%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-unquoted cookie with special char] PASSED [ 35%]\nr2e_tests/test_1.py::test_ignore_domain_ending_with_dot[pyloop] PASSED   [ 37%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_cookie_not_expired_when_added_after_removal PASSED [ 39%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_diff_host PASSED [ 41%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_host_only PASSED [ 42%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host PASSED [ 44%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_and_subdomain PASSED [ 46%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_diff_subdomain PASSED [ 48%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_expires PASSED              [ 50%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_invalid_values PASSED       [ 51%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_max_age PASSED              [ 53%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name PASSED [ 55%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order PASSED [ 57%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_different_folder PASSED [ 58%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_file PASSED     [ 60%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_folder PASSED   [ 62%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_root PASSED     [ 64%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subfolder PASSED [ 66%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subsubfolder PASSED [ 67%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_value PASSED           [ 69%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_secure_filter PASSED        [ 71%]\nr2e_tests/test_1.py::test_dummy_cookie_jar PASSED                        [ 73%]\nr2e_tests/test_1.py::test_loose_cookies_types PASSED                     [ 75%]\nr2e_tests/test_1.py::test_cookie_jar_clear_all PASSED                    [ 76%]\nr2e_tests/test_1.py::test_cookie_jar_clear_expired PASSED                [ 78%]\nr2e_tests/test_1.py::test_cookie_jar_expired_changes PASSED              [ 80%]\nr2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap PASSED  [ 82%]\nr2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires PASSED       [ 83%]\nr2e_tests/test_1.py::test_cookie_jar_heap_cleanup PASSED                 [ 85%]\nr2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup PASSED [ 87%]\nr2e_tests/test_1.py::test_cookie_jar_clear_domain PASSED                 [ 89%]\nr2e_tests/test_1.py::test_pickle_format PASSED                           [ 91%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[http://127.0.0.1/index.html] PASSED [ 92%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url1] PASSED       [ 94%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url2] PASSED       [ 96%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url3] PASSED       [ 98%]\nr2e_tests/test_1.py::test_treat_as_secure_origin PASSED                  [100%]\n\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                      Stmts   Miss Branch BrPart  Cover\n---------------------------------------------------------------------------\naiohttp/__init__.py                          27      2      2      0    93%\naiohttp/_websocket/__init__.py                0      0      0      0   100%\naiohttp/_websocket/helpers.py                77     52     38      0    22%\naiohttp/_websocket/models.py                 51      4      0      0    92%\naiohttp/_websocket/reader.py                  5      0      0      0   100%\naiohttp/_websocket/reader_py.py             208    180     92      0    10%\naiohttp/_websocket/writer.py                 75     58     24      0    17%\naiohttp/abc.py                               98      7      0      0    93%\naiohttp/base_protocol.py                     68     51     22      0    19%\naiohttp/client.py                           561    413    210      3    20%\naiohttp/client_exceptions.py                156     69     20      0    49%\naiohttp/client_proto.py                     164    131     56      0    15%\naiohttp/client_reqrep.py                    695    521    292      0    18%\naiohttp/client_ws.py                        274    217     84      1    17%\naiohttp/compression_utils.py                 70     36     14      0    40%\naiohttp/connector.py                        761    615    332      1    14%\naiohttp/cookiejar.py                        277      7    132      2    97%\naiohttp/formdata.py                          97     79     46      0    13%\naiohttp/hdrs.py                              90      0      0      0   100%\naiohttp/helpers.py                          470    305    168      1    29%\naiohttp/http.py                              11      0      2      0   100%\naiohttp/http_exceptions.py                   50     20      4      0    56%\naiohttp/http_parser.py                      508    412    210      1    14%\naiohttp/http_websocket.py                     6      0      0      0   100%\naiohttp/http_writer.py                      119     82     50      0    22%\naiohttp/log.py                                7      0      0      0   100%\naiohttp/multipart.py                        623    508    266      1    13%\naiohttp/payload.py                          237    113     58      1    44%\naiohttp/payload_streamer.py                  31     11      4      0    69%\naiohttp/pytest_plugin.py                    163     77     42      4    51%\naiohttp/resolver.py                          79     58     26      0    20%\naiohttp/streams.py                          413    325    152      0    16%\naiohttp/tcp_helpers.py                       19     11      6      0    32%\naiohttp/test_utils.py                       324    199     54      4    34%\naiohttp/tracing.py                          191     69     32      0    69%\naiohttp/typedefs.py                          24      0      0      0   100%\naiohttp/web.py                              126     88     54      0    22%\naiohttp/web_app.py                          292    196     82      0    26%\naiohttp/web_exceptions.py                   157     25      8      0    80%\naiohttp/web_fileresponse.py                 160    126     52      0    18%\naiohttp/web_log.py                          102     58     20      0    36%\naiohttp/web_middlewares.py                   59     46     22      0    16%\naiohttp/web_protocol.py                     367    306    158      0    12%\naiohttp/web_request.py                      445    294    140      1    27%\naiohttp/web_response.py                     485    367    226      0    17%\naiohttp/web_routedef.py                     100     44     10      0    55%\naiohttp/web_runner.py                       213    130     36      0    33%\naiohttp/web_server.py                        42     24     12      0    33%\naiohttp/web_urldispatcher.py                740    474    163      0    29%\naiohttp/web_ws.py                           388    312    136      1    15%\naiohttp/worker.py                           126     93     30      0    21%\ntests/conftest.py                           131    131     16      0     0%\ntests/test_base_protocol.py                 198    198      2      0     0%\ntests/test_benchmarks_client.py              18     18      2      0     0%\ntests/test_benchmarks_client_request.py      48     48      2      0     0%\ntests/test_benchmarks_client_ws.py           66     66     12      0     0%\ntests/test_benchmarks_cookiejar.py           14     14      0      0     0%\ntests/test_benchmarks_http_websocket.py      49     49      8      0     0%\ntests/test_benchmarks_http_writer.py         11     11      2      0     0%\ntests/test_circular_imports.py               29     29     13      0     0%\ntests/test_classbasedview.py                 39     39      0      0     0%\ntests/test_client_connection.py              94     94      2      0     0%\ntests/test_client_exceptions.py             199    199     14      0     0%\ntests/test_client_fingerprint.py             59     59      0      0     0%\ntests/test_client_functional.py            2616   2616     88      0     0%\ntests/test_client_proto.py                   99     99      0      0     0%\ntests/test_client_request.py                827    827     18      0     0%\ntests/test_client_response.py               480    480      6      0     0%\ntests/test_client_session.py                593    593     29      0     0%\ntests/test_client_ws.py                     489    489      2      0     0%\ntests/test_client_ws_functional.py          831    831     32      0     0%\ntests/test_connector.py                    2050   2050    106      0     0%\ntests/test_cookiejar.py                     466    466     32      0     0%\ntests/test_flowcontrol_streams.py            96     96      0      0     0%\ntests/test_formdata.py                       86     86      6      0     0%\ntests/test_helpers.py                       454    454     22      0     0%\ntests/test_http_exceptions.py               109    109     10      0     0%\ntests/test_http_parser.py                  1092   1092     66      0     0%\ntests/test_http_writer.py                   182    182     10      0     0%\ntests/test_imports.py                        34     34      6      0     0%\ntests/test_loop.py                           36     36      0      0     0%\ntests/test_multipart.py                     826    826     32      0     0%\ntests/test_multipart_helpers.py             446    446      0      0     0%\ntests/test_payload.py                        95     95      0      0     0%\ntests/test_proxy.py                         324    324      2      0     0%\ntests/test_proxy_functional.py              459    459     18      0     0%\ntests/test_pytest_plugin.py                  27     27      0      0     0%\ntests/test_resolver.py                      231    231     20      0     0%\ntests/test_route_def.py                     210    210      0      0     0%\ntests/test_run_app.py                       563    563     30      0     0%\ntests/test_streams.py                      1077   1077     38      0     0%\ntests/test_tcp_helpers.py                    52     52      2      0     0%\ntests/test_test_utils.py                    273    273     12      0     0%\ntests/test_tracing.py                        48     48      0      0     0%\ntests/test_urldispatch.py                   859    859     24      0     0%\ntests/test_web_app.py                       454    454      6      0     0%\ntests/test_web_cli.py                        94     94      0      0     0%\ntests/test_web_exceptions.py                179    179     22      0     0%\ntests/test_web_functional.py               1605   1605     36      0     0%\ntests/test_web_log.py                       116    116      2      0     0%\ntests/test_web_middleware.py                268    268     16      0     0%\ntests/test_web_request.py                   513    513      8      0     0%\ntests/test_web_request_handler.py            42     42      0      0     0%\ntests/test_web_response.py                  905    905      6      0     0%\ntests/test_web_runner.py                    151    151      4      0     0%\ntests/test_web_sendfile.py                   84     84      0      0     0%\ntests/test_web_sendfile_functional.py       673    673     18      0     0%\ntests/test_web_server.py                    162    162      0      0     0%\ntests/test_web_urldispatcher.py             524    524     24      0     0%\ntests/test_web_websocket.py                 444    444      8      0     0%\ntests/test_web_websocket_functional.py      862    862     28      0     0%\ntests/test_websocket_handshake.py           152    152     12      0     0%\ntests/test_websocket_parser.py              364    364     12      0     0%\ntests/test_websocket_writer.py               95     95      6      0     0%\ntests/test_worker.py                        191    191      2      0     0%\n---------------------------------------------------------------------------\nTOTAL                                     35694  32078   4481     21    10%\n\n============================= slowest 10 durations =============================\n0.10s call     r2e_tests/test_1.py::TestCookieJarSafe::test_expires\n0.07s call     r2e_tests/test_1.py::test_update_cookie_with_unicode_domain[pyloop]\n0.04s call     r2e_tests/test_1.py::test_cookie_jar_clear_expired\n0.04s call     r2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup\n0.03s call     r2e_tests/test_1.py::test_cookie_jar_heap_cleanup\n0.03s teardown r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-IP domain preserved]\n0.03s call     r2e_tests/test_1.py::TestCookieJarSafe::test_max_age\n0.03s call     r2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap\n0.03s call     r2e_tests/test_1.py::test_cookie_jar_expired_changes\n0.02s call     r2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_date_parsing\nPASSED r2e_tests/test_1.py::test_domain_matching\nPASSED r2e_tests/test_1.py::test_constructor[pyloop]\nPASSED r2e_tests/test_1.py::test_constructor_with_expired[pyloop]\nPASSED r2e_tests/test_1.py::test_save_load[pyloop]\nPASSED r2e_tests/test_1.py::test_update_cookie_with_unicode_domain[pyloop]\nPASSED r2e_tests/test_1.py::test_filter_cookie_with_unicode_domain[pyloop]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/-expected_cookies0]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two-expected_cookies1]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/three/-expected_cookies2]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://test1.example.com/-expected_cookies3]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/-expected_cookies4]\nPASSED r2e_tests/test_1.py::test_filter_cookies_str_deprecated[pyloop]\nPASSED r2e_tests/test_1.py::test_domain_filter_ip_cookie_send\nPASSED r2e_tests/test_1.py::test_domain_filter_ip_cookie_receive\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-IP domain preserved]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-no shared cookie]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie with special char]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie w/o special char]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-unquoted cookie with special char]\nPASSED r2e_tests/test_1.py::test_ignore_domain_ending_with_dot[pyloop]\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_cookie_not_expired_when_added_after_removal\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_diff_host\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_host_only\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_and_subdomain\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_diff_subdomain\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_expires\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_invalid_values\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_max_age\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_different_folder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_file\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_folder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_root\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subfolder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subsubfolder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_value\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_secure_filter\nPASSED r2e_tests/test_1.py::test_dummy_cookie_jar\nPASSED r2e_tests/test_1.py::test_loose_cookies_types\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_all\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_expired\nPASSED r2e_tests/test_1.py::test_cookie_jar_expired_changes\nPASSED r2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap\nPASSED r2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires\nPASSED r2e_tests/test_1.py::test_cookie_jar_heap_cleanup\nPASSED r2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_domain\nPASSED r2e_tests/test_1.py::test_pickle_format\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[http://127.0.0.1/index.html]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url1]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url2]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url3]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin\n============================== 56 passed in 5.92s ==============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/.venv/bin/python\ncodspeed: 3.0.0 (disabled, mode: walltime, timer_resolution: 1.0ns)\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1, codspeed-3.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 56 items\n\nr2e_tests/test_1.py::test_date_parsing PASSED                            [  1%]\nr2e_tests/test_1.py::test_domain_matching PASSED                         [  3%]\nr2e_tests/test_1.py::test_constructor[pyloop] PASSED                     [  5%]\nr2e_tests/test_1.py::test_constructor_with_expired[pyloop] PASSED        [  7%]\nr2e_tests/test_1.py::test_save_load[pyloop] PASSED                       [  8%]\nr2e_tests/test_1.py::test_update_cookie_with_unicode_domain[pyloop] PASSED [ 10%]\nr2e_tests/test_1.py::test_filter_cookie_with_unicode_domain[pyloop] PASSED [ 12%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/-expected_cookies0] PASSED [ 14%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two-expected_cookies1] PASSED [ 16%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/three/-expected_cookies2] PASSED [ 17%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://test1.example.com/-expected_cookies3] PASSED [ 19%]\nr2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/-expected_cookies4] PASSED [ 21%]\nr2e_tests/test_1.py::test_filter_cookies_str_deprecated[pyloop] FAILED   [ 23%]\nr2e_tests/test_1.py::test_domain_filter_ip_cookie_send PASSED            [ 25%]\nr2e_tests/test_1.py::test_domain_filter_ip_cookie_receive PASSED         [ 26%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-IP domain preserved] PASSED [ 28%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-no shared cookie] PASSED [ 30%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie with special char] PASSED [ 32%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie w/o special char] PASSED [ 33%]\nr2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-unquoted cookie with special char] PASSED [ 35%]\nr2e_tests/test_1.py::test_ignore_domain_ending_with_dot[pyloop] PASSED   [ 37%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_cookie_not_expired_when_added_after_removal PASSED [ 39%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_diff_host PASSED [ 41%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_host_only PASSED [ 42%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host PASSED [ 44%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_and_subdomain PASSED [ 46%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_diff_subdomain PASSED [ 48%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_expires PASSED              [ 50%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_invalid_values PASSED       [ 51%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_max_age PASSED              [ 53%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name PASSED [ 55%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order PASSED [ 57%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_different_folder PASSED [ 58%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_file PASSED     [ 60%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_folder PASSED   [ 62%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_root PASSED     [ 64%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subfolder PASSED [ 66%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subsubfolder PASSED [ 67%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_path_value PASSED           [ 69%]\nr2e_tests/test_1.py::TestCookieJarSafe::test_secure_filter PASSED        [ 71%]\nr2e_tests/test_1.py::test_dummy_cookie_jar PASSED                        [ 73%]\nr2e_tests/test_1.py::test_loose_cookies_types PASSED                     [ 75%]\nr2e_tests/test_1.py::test_cookie_jar_clear_all PASSED                    [ 76%]\nr2e_tests/test_1.py::test_cookie_jar_clear_expired PASSED                [ 78%]\nr2e_tests/test_1.py::test_cookie_jar_expired_changes PASSED              [ 80%]\nr2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap PASSED  [ 82%]\nr2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires PASSED       [ 83%]\nr2e_tests/test_1.py::test_cookie_jar_heap_cleanup PASSED                 [ 85%]\nr2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup PASSED [ 87%]\nr2e_tests/test_1.py::test_cookie_jar_clear_domain PASSED                 [ 89%]\nr2e_tests/test_1.py::test_pickle_format PASSED                           [ 91%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[http://127.0.0.1/index.html] PASSED [ 92%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url1] PASSED       [ 94%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url2] PASSED       [ 96%]\nr2e_tests/test_1.py::test_treat_as_secure_origin_init[url3] PASSED       [ 98%]\nr2e_tests/test_1.py::test_treat_as_secure_origin PASSED                  [100%]\n\n=================================== FAILURES ===================================\n__________________ test_filter_cookies_str_deprecated[pyloop] __________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_filter_cookies_str_deprecated(loop: asyncio.AbstractEventLoop) -> None:\n        jar = CookieJar()\n        jar.update_cookies(SimpleCookie(\"shared-cookie=first; Domain=example.com;\"))\n        with pytest.warns(DeprecationWarning):\n>           jar.filter_cookies(\"http://éé.com\")\nE           Failed: DID NOT WARN. No warnings of type (<class 'DeprecationWarning'>,) were emitted.\nE            Emitted warnings: [].\n\njar        = <aiohttp.cookiejar.CookieJar object at 0x72f878692430>\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:320: Failed\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                      Stmts   Miss Branch BrPart  Cover\n---------------------------------------------------------------------------\naiohttp/__init__.py                          27      2      2      0    93%\naiohttp/_websocket/__init__.py                0      0      0      0   100%\naiohttp/_websocket/helpers.py                77     52     38      0    22%\naiohttp/_websocket/models.py                 51      4      0      0    92%\naiohttp/_websocket/reader.py                  5      0      0      0   100%\naiohttp/_websocket/reader_py.py             208    180     92      0    10%\naiohttp/_websocket/writer.py                 75     58     24      0    17%\naiohttp/abc.py                               98      7      0      0    93%\naiohttp/base_protocol.py                     68     51     22      0    19%\naiohttp/client.py                           561    413    210      3    20%\naiohttp/client_exceptions.py                156     69     20      0    49%\naiohttp/client_proto.py                     164    131     56      0    15%\naiohttp/client_reqrep.py                    695    521    292      0    18%\naiohttp/client_ws.py                        274    217     84      1    17%\naiohttp/compression_utils.py                 70     36     14      0    40%\naiohttp/connector.py                        761    615    332      1    14%\naiohttp/cookiejar.py                        274      7    130      2    97%\naiohttp/formdata.py                          97     79     46      0    13%\naiohttp/hdrs.py                              90      0      0      0   100%\naiohttp/helpers.py                          470    305    168      1    29%\naiohttp/http.py                              11      0      2      0   100%\naiohttp/http_exceptions.py                   50     20      4      0    56%\naiohttp/http_parser.py                      508    412    210      1    14%\naiohttp/http_websocket.py                     6      0      0      0   100%\naiohttp/http_writer.py                      119     82     50      0    22%\naiohttp/log.py                                7      0      0      0   100%\naiohttp/multipart.py                        623    508    266      1    13%\naiohttp/payload.py                          237    113     58      1    44%\naiohttp/payload_streamer.py                  31     11      4      0    69%\naiohttp/pytest_plugin.py                    163     76     42      4    51%\naiohttp/resolver.py                          79     58     26      0    20%\naiohttp/streams.py                          413    325    152      0    16%\naiohttp/tcp_helpers.py                       19     11      6      0    32%\naiohttp/test_utils.py                       324    199     54      4    34%\naiohttp/tracing.py                          191     69     32      0    69%\naiohttp/typedefs.py                          24      0      0      0   100%\naiohttp/web.py                              126     88     54      0    22%\naiohttp/web_app.py                          292    196     82      0    26%\naiohttp/web_exceptions.py                   157     25      8      0    80%\naiohttp/web_fileresponse.py                 160    126     52      0    18%\naiohttp/web_log.py                          102     58     20      0    36%\naiohttp/web_middlewares.py                   59     46     22      0    16%\naiohttp/web_protocol.py                     367    306    158      0    12%\naiohttp/web_request.py                      445    294    140      1    27%\naiohttp/web_response.py                     485    367    226      0    17%\naiohttp/web_routedef.py                     100     44     10      0    55%\naiohttp/web_runner.py                       213    130     36      0    33%\naiohttp/web_server.py                        42     24     12      0    33%\naiohttp/web_urldispatcher.py                740    474    163      0    29%\naiohttp/web_ws.py                           388    312    136      1    15%\naiohttp/worker.py                           126     93     30      0    21%\ntests/conftest.py                           131    131     16      0     0%\ntests/test_base_protocol.py                 198    198      2      0     0%\ntests/test_benchmarks_client.py              18     18      2      0     0%\ntests/test_benchmarks_client_request.py      48     48      2      0     0%\ntests/test_benchmarks_client_ws.py           66     66     12      0     0%\ntests/test_benchmarks_cookiejar.py           14     14      0      0     0%\ntests/test_benchmarks_http_websocket.py      49     49      8      0     0%\ntests/test_benchmarks_http_writer.py         11     11      2      0     0%\ntests/test_circular_imports.py               29     29     13      0     0%\ntests/test_classbasedview.py                 39     39      0      0     0%\ntests/test_client_connection.py              94     94      2      0     0%\ntests/test_client_exceptions.py             199    199     14      0     0%\ntests/test_client_fingerprint.py             59     59      0      0     0%\ntests/test_client_functional.py            2616   2616     88      0     0%\ntests/test_client_proto.py                   99     99      0      0     0%\ntests/test_client_request.py                827    827     18      0     0%\ntests/test_client_response.py               480    480      6      0     0%\ntests/test_client_session.py                593    593     29      0     0%\ntests/test_client_ws.py                     489    489      2      0     0%\ntests/test_client_ws_functional.py          831    831     32      0     0%\ntests/test_connector.py                    2050   2050    106      0     0%\ntests/test_cookiejar.py                     461    461     32      0     0%\ntests/test_flowcontrol_streams.py            96     96      0      0     0%\ntests/test_formdata.py                       86     86      6      0     0%\ntests/test_helpers.py                       454    454     22      0     0%\ntests/test_http_exceptions.py               109    109     10      0     0%\ntests/test_http_parser.py                  1092   1092     66      0     0%\ntests/test_http_writer.py                   182    182     10      0     0%\ntests/test_imports.py                        34     34      6      0     0%\ntests/test_loop.py                           36     36      0      0     0%\ntests/test_multipart.py                     826    826     32      0     0%\ntests/test_multipart_helpers.py             446    446      0      0     0%\ntests/test_payload.py                        95     95      0      0     0%\ntests/test_proxy.py                         324    324      2      0     0%\ntests/test_proxy_functional.py              459    459     18      0     0%\ntests/test_pytest_plugin.py                  27     27      0      0     0%\ntests/test_resolver.py                      231    231     20      0     0%\ntests/test_route_def.py                     210    210      0      0     0%\ntests/test_run_app.py                       563    563     30      0     0%\ntests/test_streams.py                      1077   1077     38      0     0%\ntests/test_tcp_helpers.py                    52     52      2      0     0%\ntests/test_test_utils.py                    273    273     12      0     0%\ntests/test_tracing.py                        48     48      0      0     0%\ntests/test_urldispatch.py                   859    859     24      0     0%\ntests/test_web_app.py                       454    454      6      0     0%\ntests/test_web_cli.py                        94     94      0      0     0%\ntests/test_web_exceptions.py                179    179     22      0     0%\ntests/test_web_functional.py               1605   1605     36      0     0%\ntests/test_web_log.py                       116    116      2      0     0%\ntests/test_web_middleware.py                268    268     16      0     0%\ntests/test_web_request.py                   513    513      8      0     0%\ntests/test_web_request_handler.py            42     42      0      0     0%\ntests/test_web_response.py                  905    905      6      0     0%\ntests/test_web_runner.py                    151    151      4      0     0%\ntests/test_web_sendfile.py                   84     84      0      0     0%\ntests/test_web_sendfile_functional.py       673    673     18      0     0%\ntests/test_web_server.py                    162    162      0      0     0%\ntests/test_web_urldispatcher.py             524    524     24      0     0%\ntests/test_web_websocket.py                 444    444      8      0     0%\ntests/test_web_websocket_functional.py      862    862     28      0     0%\ntests/test_websocket_handshake.py           152    152     12      0     0%\ntests/test_websocket_parser.py              364    364     12      0     0%\ntests/test_websocket_writer.py               95     95      6      0     0%\ntests/test_worker.py                        191    191      2      0     0%\n---------------------------------------------------------------------------\nTOTAL                                     35686  32072   4479     21    10%\n\n============================= slowest 10 durations =============================\n0.06s call     r2e_tests/test_1.py::TestCookieJarSafe::test_expires\n0.04s call     r2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup\n0.04s call     r2e_tests/test_1.py::test_cookie_jar_clear_expired\n0.04s call     r2e_tests/test_1.py::test_cookie_jar_heap_cleanup\n0.03s call     r2e_tests/test_1.py::test_pickle_format\n0.03s call     r2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires\n0.03s call     r2e_tests/test_1.py::TestCookieJarSafe::test_max_age\n0.02s call     r2e_tests/test_1.py::test_cookie_jar_expired_changes\n0.02s call     r2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap\n0.02s call     r2e_tests/test_1.py::test_dummy_cookie_jar\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_date_parsing\nPASSED r2e_tests/test_1.py::test_domain_matching\nPASSED r2e_tests/test_1.py::test_constructor[pyloop]\nPASSED r2e_tests/test_1.py::test_constructor_with_expired[pyloop]\nPASSED r2e_tests/test_1.py::test_save_load[pyloop]\nPASSED r2e_tests/test_1.py::test_update_cookie_with_unicode_domain[pyloop]\nPASSED r2e_tests/test_1.py::test_filter_cookie_with_unicode_domain[pyloop]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/-expected_cookies0]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two-expected_cookies1]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/three/-expected_cookies2]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://test1.example.com/-expected_cookies3]\nPASSED r2e_tests/test_1.py::test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/-expected_cookies4]\nPASSED r2e_tests/test_1.py::test_domain_filter_ip_cookie_send\nPASSED r2e_tests/test_1.py::test_domain_filter_ip_cookie_receive\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-IP domain preserved]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-no shared cookie]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie with special char]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-quoted cookie w/o special char]\nPASSED r2e_tests/test_1.py::test_quotes_correctly_based_on_input[pyloop-unquoted cookie with special char]\nPASSED r2e_tests/test_1.py::test_ignore_domain_ending_with_dot[pyloop]\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_cookie_not_expired_when_added_after_removal\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_diff_host\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_host_only\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_and_subdomain\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_domain_filter_same_host_diff_subdomain\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_expires\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_invalid_values\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_max_age\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_different_folder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_file\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_folder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_root\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subfolder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_filter_subsubfolder\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_path_value\nPASSED r2e_tests/test_1.py::TestCookieJarSafe::test_secure_filter\nPASSED r2e_tests/test_1.py::test_dummy_cookie_jar\nPASSED r2e_tests/test_1.py::test_loose_cookies_types\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_all\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_expired\nPASSED r2e_tests/test_1.py::test_cookie_jar_expired_changes\nPASSED r2e_tests/test_1.py::test_cookie_jar_duplicates_with_expire_heap\nPASSED r2e_tests/test_1.py::test_cookie_jar_filter_cookies_expires\nPASSED r2e_tests/test_1.py::test_cookie_jar_heap_cleanup\nPASSED r2e_tests/test_1.py::test_cookie_jar_heap_maintains_order_after_cleanup\nPASSED r2e_tests/test_1.py::test_cookie_jar_clear_domain\nPASSED r2e_tests/test_1.py::test_pickle_format\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[http://127.0.0.1/index.html]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url1]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url2]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin_init[url3]\nPASSED r2e_tests/test_1.py::test_treat_as_secure_origin\nFAILED r2e_tests/test_1.py::test_filter_cookies_str_deprecated[pyloop] - Fail...\n========================= 1 failed, 55 passed in 5.38s =========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e56a4fd45b813a8c41d09c88aaf3c73903935c71/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n"
}
aiohttp/cookiejar.py tests/test_cookiejar.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** `filter_cookies` Does Not Emit DeprecationWarning When Called with a String URL

**Description:**

When using the `filter_cookies` method of `CookieJar`, passing a URL as a string does not trigger a `DeprecationWarning` as expected. This behavior deviates from the intended functionality where only `URL` instances should be used, and passing a string should warn developers about the upcoming change.

**Example Code:**

```python
jar = CookieJar()
jar.update_cookies(SimpleCookie("shared-cookie=first; Domain=example.com;"))
jar.filter_cookies("http://éé.com")
```

**Expected Behavior:**

Calling `filter_cookies` with a string URL should emit a `DeprecationWarning` indicating that a `URL` instance is expected. This warning helps developers transition to using `URL` instances before future versions enforce this requirement.

**Actual Behavior:**

No `DeprecationWarning` is emitted when `filter_cookies` is called with a string URL. As a result, developers might be unaware of the need to update their code, leading to potential issues in future releases.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/cookiejar.py
import asyncio
import calendar
import contextlib
import datetime
import heapq
import itertools
import os  # noqa
import pathlib
import pickle
import re
import time
from collections import defaultdict
from http.cookies import BaseCookie, Morsel, SimpleCookie
from typing import (
    DefaultDict,
    Dict,
    Iterable,
    Iterator,
    List,
    Mapping,
    Optional,
    Set,
    Tuple,
    Union,
    cast,
)

from yarl import URL

from .abc import AbstractCookieJar, ClearCookiePredicate
from .helpers import is_ip_address
from .typedefs import LooseCookies, PathLike, StrOrURL

__all__ = ("CookieJar", "DummyCookieJar")


CookieItem = Union[str, "Morsel[str]"]

# We cache these string methods here as their use is in performance critical code.
_FORMAT_PATH = "{}/{}".format
_FORMAT_DOMAIN_REVERSED = "{1}.{0}".format

# The minimum number of scheduled cookie expirations before we start cleaning up
# the expiration heap. This is a performance optimization to avoid cleaning up the
# heap too often when there are only a few scheduled expirations.
_MIN_SCHEDULED_COOKIE_EXPIRATION = 100


class CookieJar(AbstractCookieJar):
    """Implements cookie storage adhering to RFC 6265."""

    DATE_TOKENS_RE = re.compile(
        r"[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]*"
        r"(?P<token>[\x00-\x08\x0A-\x1F\d:a-zA-Z\x7F-\xFF]+)"
    )

    DATE_HMS_TIME_RE = re.compile(r"(\d{1,2}):(\d{1,2}):(\d{1,2})")

    DATE_DAY_OF_MONTH_RE = re.compile(r"(\d{1,2})")

    DATE_MONTH_RE = re.compile(
        "(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)",
        re.I,
    )

    DATE_YEAR_RE = re.compile(r"(\d{2,4})")

    # calendar.timegm() fails for timestamps after datetime.datetime.max
    # Minus one as a loss of precision occurs when timestamp() is called.
    MAX_TIME = (
        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1
    )
    try:
        calendar.timegm(time.gmtime(MAX_TIME))
    except (OSError, ValueError):
        # Hit the maximum representable time on Windows
        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64
        # Throws ValueError on PyPy 3.9, OSError elsewhere
        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))
    except OverflowError:
        # #4515: datetime.max may not be representable on 32-bit platforms
        MAX_TIME = 2**31 - 1
    # Avoid minuses in the future, 3x faster
    SUB_MAX_TIME = MAX_TIME - 1

    def __init__(
        self,
        *,
        unsafe: bool = False,
        quote_cookie: bool = True,
        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,
        loop: Optional[asyncio.AbstractEventLoop] = None,
    ) -> None:
        super().__init__(loop=loop)
        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(
            SimpleCookie
        )
        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (
            defaultdict(dict)
        )
        self._host_only_cookies: Set[Tuple[str, str]] = set()
        self._unsafe = unsafe
        self._quote_cookie = quote_cookie
        if treat_as_secure_origin is None:
            treat_as_secure_origin = []
        elif isinstance(treat_as_secure_origin, URL):
            treat_as_secure_origin = [treat_as_secure_origin.origin()]
        elif isinstance(treat_as_secure_origin, str):
            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]
        else:
            treat_as_secure_origin = [
                URL(url).origin() if isinstance(url, str) else url.origin()
                for url in treat_as_secure_origin
            ]
        self._treat_as_secure_origin = treat_as_secure_origin
        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []
        self._expirations: Dict[Tuple[str, str, str], float] = {}

    def save(self, file_path: PathLike) -> None:
        file_path = pathlib.Path(file_path)
        with file_path.open(mode="wb") as f:
            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)

    def load(self, file_path: PathLike) -> None:
        file_path = pathlib.Path(file_path)
        with file_path.open(mode="rb") as f:
            self._cookies = pickle.load(f)

    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
        if predicate is None:
            self._expire_heap.clear()
            self._cookies.clear()
            self._morsel_cache.clear()
            self._host_only_cookies.clear()
            self._expirations.clear()
            return

        now = time.time()
        to_del = [
            key
            for (domain, path), cookie in self._cookies.items()
            for name, morsel in cookie.items()
            if (
                (key := (domain, path, name)) in self._expirations
                and self._expirations[key] <= now
            )
            or predicate(morsel)
        ]
        if to_del:
            self._delete_cookies(to_del)

    def clear_domain(self, domain: str) -> None:
        self.clear(lambda x: self._is_domain_match(domain, x["domain"]))

    def __iter__(self) -> "Iterator[Morsel[str]]":
        self._do_expiration()
        for val in self._cookies.values():
            yield from val.values()

    def __len__(self) -> int:
        """Return number of cookies.

        This function does not iterate self to avoid unnecessary expiration
        checks.
        """
        return sum(len(cookie.values()) for cookie in self._cookies.values())

    def _do_expiration(self) -> None:
        """Remove expired cookies."""
        if not (expire_heap_len := len(self._expire_heap)):
            return

        # If the expiration heap grows larger than the number expirations
        # times two, we clean it up to avoid keeping expired entries in
        # the heap and consuming memory. We guard this with a minimum
        # threshold to avoid cleaning up the heap too often when there are
        # only a few scheduled expirations.
        if (
            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION
            and expire_heap_len > len(self._expirations) * 2
        ):
            # Remove any expired entries from the expiration heap
            # that do not match the expiration time in the expirations
            # as it means the cookie has been re-added to the heap
            # with a different expiration time.
            self._expire_heap = [
                entry
                for entry in self._expire_heap
                if self._expirations.get(entry[1]) == entry[0]
            ]
            heapq.heapify(self._expire_heap)

        now = time.time()
        to_del: List[Tuple[str, str, str]] = []
        # Find any expired cookies and add them to the to-delete list
        while self._expire_heap:
            when, cookie_key = self._expire_heap[0]
            if when > now:
                break
            heapq.heappop(self._expire_heap)
            # Check if the cookie hasn't been re-added to the heap
            # with a different expiration time as it will be removed
            # later when it reaches the top of the heap and its
            # expiration time is met.
            if self._expirations.get(cookie_key) == when:
                to_del.append(cookie_key)

        if to_del:
            self._delete_cookies(to_del)

    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:
        for domain, path, name in to_del:
            self._host_only_cookies.discard((domain, name))
            self._cookies[(domain, path)].pop(name, None)
            self._morsel_cache[(domain, path)].pop(name, None)
            self._expirations.pop((domain, path, name), None)

    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:
        cookie_key = (domain, path, name)
        if self._expirations.get(cookie_key) == when:
            # Avoid adding duplicates to the heap
            return
        heapq.heappush(self._expire_heap, (when, cookie_key))
        self._expirations[cookie_key] = when

    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
        """Update cookies."""
        hostname = response_url.raw_host

        if not self._unsafe and is_ip_address(hostname):
            # Don't accept cookies from IPs
            return

        if isinstance(cookies, Mapping):
            cookies = cookies.items()

        for name, cookie in cookies:
            if not isinstance(cookie, Morsel):
                tmp = SimpleCookie()
                tmp[name] = cookie  # type: ignore[assignment]
                cookie = tmp[name]

            domain = cookie["domain"]

            # ignore domains with trailing dots
            if domain and domain[-1] == ".":
                domain = ""
                del cookie["domain"]

            if not domain and hostname is not None:
                # Set the cookie's domain to the response hostname
                # and set its host-only-flag
                self._host_only_cookies.add((hostname, name))
                domain = cookie["domain"] = hostname

            if domain and domain[0] == ".":
                # Remove leading dot
                domain = domain[1:]
                cookie["domain"] = domain

            if hostname and not self._is_domain_match(domain, hostname):
                # Setting cookies for different domains is not allowed
                continue

            path = cookie["path"]
            if not path or path[0] != "/":
                # Set the cookie's path to the response path
                path = response_url.path
                if not path.startswith("/"):
                    path = "/"
                else:
                    # Cut everything from the last slash to the end
                    path = "/" + path[1 : path.rfind("/")]
                cookie["path"] = path
            path = path.rstrip("/")

            if max_age := cookie["max-age"]:
                try:
                    delta_seconds = int(max_age)
                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)
                    self._expire_cookie(max_age_expiration, domain, path, name)
                except ValueError:
                    cookie["max-age"] = ""

            elif expires := cookie["expires"]:
                if expire_time := self._parse_date(expires):
                    self._expire_cookie(expire_time, domain, path, name)
                else:
                    cookie["expires"] = ""

            key = (domain, path)
            if self._cookies[key].get(name) != cookie:
                # Don't blow away the cache if the same
                # cookie gets set again
                self._cookies[key][name] = cookie
                self._morsel_cache[key].pop(name, None)

        self._do_expiration()

    def filter_cookies(self, request_url: URL = URL()) -> "BaseCookie[str]":
        """Returns this jar's cookies filtered by their attributes."""
        filtered: Union[SimpleCookie, "BaseCookie[str]"] = (
            SimpleCookie() if self._quote_cookie else BaseCookie()
        )
        if not self._cookies:
            # Skip do_expiration() if there are no cookies.
            return filtered
        self._do_expiration()
        if not self._cookies:
            # Skip rest of function if no non-expired cookies.
            return filtered
        request_url = URL(request_url)
        hostname = request_url.raw_host or ""

        is_not_secure = request_url.scheme not in ("https", "wss")
        if is_not_secure and self._treat_as_secure_origin:
            request_origin = URL()
            with contextlib.suppress(ValueError):
                request_origin = request_url.origin()
            is_not_secure = request_origin not in self._treat_as_secure_origin

        # Send shared cookie
        for c in self._cookies[("", "")].values():
            filtered[c.key] = c.value

        if is_ip_address(hostname):
            if not self._unsafe:
                return filtered
            domains: Iterable[str] = (hostname,)
        else:
            # Get all the subdomains that might match a cookie (e.g. "foo.bar.com", "bar.com", "com")
            domains = itertools.accumulate(
                reversed(hostname.split(".")), _FORMAT_DOMAIN_REVERSED
            )

        # Get all the path prefixes that might match a cookie (e.g. "", "/foo", "/foo/bar")
        paths = itertools.accumulate(request_url.path.split("/"), _FORMAT_PATH)
        # Create every combination of (domain, path) pairs.
        pairs = itertools.product(domains, paths)

        path_len = len(request_url.path)
        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4
        for p in pairs:
            for name, cookie in self._cookies[p].items():
                domain = cookie["domain"]

                if (domain, name) in self._host_only_cookies and domain != hostname:
                    continue

                # Skip edge case when the cookie has a trailing slash but request doesn't.
                if len(cookie["path"]) > path_len:
                    continue

                if is_not_secure and cookie["secure"]:
                    continue

                # We already built the Morsel so reuse it here
                if name in self._morsel_cache[p]:
                    filtered[name] = self._morsel_cache[p][name]
                    continue

                # It's critical we use the Morsel so the coded_value
                # (based on cookie version) is preserved
                mrsl_val = cast("Morsel[str]", cookie.get(cookie.key, Morsel()))
                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)
                self._morsel_cache[p][name] = mrsl_val
                filtered[name] = mrsl_val

        return filtered

    @staticmethod
    def _is_domain_match(domain: str, hostname: str) -> bool:
        """Implements domain matching adhering to RFC 6265."""
        if hostname == domain:
            return True

        if not hostname.endswith(domain):
            return False

        non_matching = hostname[: -len(domain)]

        if not non_matching.endswith("."):
            return False

        return not is_ip_address(hostname)

    @classmethod
    def _parse_date(cls, date_str: str) -> Optional[int]:
        """Implements date string parsing adhering to RFC 6265."""
        if not date_str:
            return None

        found_time = False
        found_day = False
        found_month = False
        found_year = False

        hour = minute = second = 0
        day = 0
        month = 0
        year = 0

        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):

            token = token_match.group("token")

            if not found_time:
                time_match = cls.DATE_HMS_TIME_RE.match(token)
                if time_match:
                    found_time = True
                    hour, minute, second = (int(s) for s in time_match.groups())
                    continue

            if not found_day:
                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)
                if day_match:
                    found_day = True
                    day = int(day_match.group())
                    continue

            if not found_month:
                month_match = cls.DATE_MONTH_RE.match(token)
                if month_match:
                    found_month = True
                    assert month_match.lastindex is not None
                    month = month_match.lastindex
                    continue

            if not found_year:
                year_match = cls.DATE_YEAR_RE.match(token)
                if year_match:
                    found_year = True
                    year = int(year_match.group())

        if 70 <= year <= 99:
            year += 1900
        elif 0 <= year <= 69:
            year += 2000

        if False in (found_day, found_month, found_year, found_time):
            return None

        if not 1 <= day <= 31:
            return None

        if year < 1601 or hour > 23 or minute > 59 or second > 59:
            return None

        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))


class DummyCookieJar(AbstractCookieJar):
    """Implements a dummy cookie storage.

    It can be used with the ClientSession when no cookie processing is needed.

    """

    def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:
        super().__init__(loop=loop)

    def __iter__(self) -> "Iterator[Morsel[str]]":
        while False:
            yield None

    def __len__(self) -> int:
        return 0

    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
        pass

    def clear_domain(self, domain: str) -> None:
        pass

    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
        pass

    def filter_cookies(self, request_url: URL) -> "BaseCookie[str]":
        return SimpleCookie()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]

**Title:** `filter_cookies` Does Not Emit DeprecationWarning When Called with a String URL

**Description:**

When using the `filter_cookies` method of `CookieJar`, passing a URL as a string does not trigger a `DeprecationWarning` as expected. This behavior deviates from the intended functionality where only `URL` instances should be used, and passing a string should warn developers about the upcoming change.

**Example Code:**

```python
jar = CookieJar()
jar.update_cookies(SimpleCookie("shared-cookie=first; Domain=example.com;"))
jar.filter_cookies("http://éé.com")
```

**Expected Behavior:**

Calling `filter_cookies` with a string URL should emit a `DeprecationWarning` indicating that a `URL` instance is expected. This warning helps developers transition to using `URL` instances before future versions enforce this requirement.

**Actual Behavior:**

No `DeprecationWarning` is emitted when `filter_cookies` is called with a string URL. As a result, developers might be unaware of the need to update their code, leading to potential issues in future releases.

[/ISSUE]
{
    "test_date_parsing": "PASSED",
    "test_domain_matching": "PASSED",
    "test_constructor[pyloop]": "PASSED",
    "test_constructor_with_expired[pyloop]": "PASSED",
    "test_save_load[pyloop]": "PASSED",
    "test_update_cookie_with_unicode_domain[pyloop]": "PASSED",
    "test_filter_cookie_with_unicode_domain[pyloop]": "PASSED",
    "test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/-expected_cookies0]": "PASSED",
    "test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two-expected_cookies1]": "PASSED",
    "test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/one/two/three/-expected_cookies2]": "PASSED",
    "test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://test1.example.com/-expected_cookies3]": "PASSED",
    "test_filter_cookies_with_domain_path_lookup_multilevelpath[pyloop-http://pathtest.com/-expected_cookies4]": "PASSED",
    "test_filter_cookies_str_deprecated[pyloop]": "PASSED",
    "test_domain_filter_ip_cookie_send": "PASSED",
    "test_domain_filter_ip_cookie_receive": "PASSED",
    "test_quotes_correctly_based_on_input[pyloop-IP domain preserved]": "PASSED",
    "test_quotes_correctly_based_on_input[pyloop-no shared cookie]": "PASSED",
    "test_quotes_correctly_based_on_input[pyloop-quoted cookie with special char]": "PASSED",
    "test_quotes_correctly_based_on_input[pyloop-quoted cookie w/o special char]": "PASSED",
    "test_quotes_correctly_based_on_input[pyloop-unquoted cookie with special char]": "PASSED",
    "test_ignore_domain_ending_with_dot[pyloop]": "PASSED",
    "TestCookieJarSafe.test_cookie_not_expired_when_added_after_removal": "PASSED",
    "TestCookieJarSafe.test_domain_filter_diff_host": "PASSED",
    "TestCookieJarSafe.test_domain_filter_host_only": "PASSED",
    "TestCookieJarSafe.test_domain_filter_same_host": "PASSED",
    "TestCookieJarSafe.test_domain_filter_same_host_and_subdomain": "PASSED",
    "TestCookieJarSafe.test_domain_filter_same_host_diff_subdomain": "PASSED",
    "TestCookieJarSafe.test_expires": "PASSED",
    "TestCookieJarSafe.test_invalid_values": "PASSED",
    "TestCookieJarSafe.test_max_age": "PASSED",
    "TestCookieJarSafe.test_path_filter_diff_folder_same_name": "PASSED",
    "TestCookieJarSafe.test_path_filter_diff_folder_same_name_return_best_match_independent_from_put_order": "PASSED",
    "TestCookieJarSafe.test_path_filter_different_folder": "PASSED",
    "TestCookieJarSafe.test_path_filter_file": "PASSED",
    "TestCookieJarSafe.test_path_filter_folder": "PASSED",
    "TestCookieJarSafe.test_path_filter_root": "PASSED",
    "TestCookieJarSafe.test_path_filter_subfolder": "PASSED",
    "TestCookieJarSafe.test_path_filter_subsubfolder": "PASSED",
    "TestCookieJarSafe.test_path_value": "PASSED",
    "TestCookieJarSafe.test_secure_filter": "PASSED",
    "test_dummy_cookie_jar": "PASSED",
    "test_loose_cookies_types": "PASSED",
    "test_cookie_jar_clear_all": "PASSED",
    "test_cookie_jar_clear_expired": "PASSED",
    "test_cookie_jar_expired_changes": "PASSED",
    "test_cookie_jar_duplicates_with_expire_heap": "PASSED",
    "test_cookie_jar_filter_cookies_expires": "PASSED",
    "test_cookie_jar_heap_cleanup": "PASSED",
    "test_cookie_jar_heap_maintains_order_after_cleanup": "PASSED",
    "test_cookie_jar_clear_domain": "PASSED",
    "test_pickle_format": "PASSED",
    "test_treat_as_secure_origin_init[http://127.0.0.1/index.html]": "PASSED",
    "test_treat_as_secure_origin_init[url1]": "PASSED",
    "test_treat_as_secure_origin_init[url2]": "PASSED",
    "test_treat_as_secure_origin_init[url3]": "PASSED",
    "test_treat_as_secure_origin": "PASSED"
}
diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py
index 3ffa4198..ef04bda5 100644
--- a/aiohttp/cookiejar.py
+++ b/aiohttp/cookiejar.py
@@ -9,6 +9,7 @@ import pathlib
 import pickle
 import re
 import time
+import warnings
 from collections import defaultdict
 from http.cookies import BaseCookie, Morsel, SimpleCookie
 from typing import (
@@ -309,7 +310,14 @@ class CookieJar(AbstractCookieJar):
         if not self._cookies:
             # Skip rest of function if no non-expired cookies.
             return filtered
-        request_url = URL(request_url)
+        if type(request_url) is not URL:
+            warnings.warn(
+                "filter_cookies expects yarl.URL instances only,"
+                f"and will stop working in 4.x, got {type(request_url)}",
+                DeprecationWarning,
+                stacklevel=2,
+            )
+            request_url = URL(request_url)
         hostname = request_url.raw_host or ""
 
         is_not_secure = request_url.scheme not in ("https", "wss")

{"aiohttp/cookiejar.py": "import asyncio\nimport calendar\nimport contextlib\nimport datetime\nimport heapq\nimport itertools\nimport os  # noqa\nimport pathlib\nimport pickle\nimport re\nimport time\nfrom collections import defaultdict\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import (\n    DefaultDict,\n    Dict,\n    Iterable,\n    Iterator,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Union,\n    cast,\n)\n\nfrom yarl import URL\n\nfrom .abc import AbstractCookieJar, ClearCookiePredicate\nfrom .helpers import is_ip_address\nfrom .typedefs import LooseCookies, PathLike, StrOrURL\n\n__all__ = (\"CookieJar\", \"DummyCookieJar\")\n\n\nCookieItem = Union[str, \"Morsel[str]\"]\n\n# We cache these string methods here as their use is in performance critical code.\n_FORMAT_PATH = \"{}/{}\".format\n_FORMAT_DOMAIN_REVERSED = \"{1}.{0}\".format\n\n# The minimum number of scheduled cookie expirations before we start cleaning up\n# the expiration heap. This is a performance optimization to avoid cleaning up the\n# heap too often when there are only a few scheduled expirations.\n_MIN_SCHEDULED_COOKIE_EXPIRATION = 100\n\n\nclass CookieJar(AbstractCookieJar):\n    \"\"\"Implements cookie storage adhering to RFC 6265.\"\"\"\n\n    DATE_TOKENS_RE = re.compile(\n        r\"[\\x09\\x20-\\x2F\\x3B-\\x40\\x5B-\\x60\\x7B-\\x7E]*\"\n        r\"(?P<token>[\\x00-\\x08\\x0A-\\x1F\\d:a-zA-Z\\x7F-\\xFF]+)\"\n    )\n\n    DATE_HMS_TIME_RE = re.compile(r\"(\\d{1,2}):(\\d{1,2}):(\\d{1,2})\")\n\n    DATE_DAY_OF_MONTH_RE = re.compile(r\"(\\d{1,2})\")\n\n    DATE_MONTH_RE = re.compile(\n        \"(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)\",\n        re.I,\n    )\n\n    DATE_YEAR_RE = re.compile(r\"(\\d{2,4})\")\n\n    # calendar.timegm() fails for timestamps after datetime.datetime.max\n    # Minus one as a loss of precision occurs when timestamp() is called.\n    MAX_TIME = (\n        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1\n    )\n    try:\n        calendar.timegm(time.gmtime(MAX_TIME))\n    except (OSError, ValueError):\n        # Hit the maximum representable time on Windows\n        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64\n        # Throws ValueError on PyPy 3.9, OSError elsewhere\n        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))\n    except OverflowError:\n        # #4515: datetime.max may not be representable on 32-bit platforms\n        MAX_TIME = 2**31 - 1\n    # Avoid minuses in the future, 3x faster\n    SUB_MAX_TIME = MAX_TIME - 1\n\n    def __init__(\n        self,\n        *,\n        unsafe: bool = False,\n        quote_cookie: bool = True,\n        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n    ) -> None:\n        super().__init__(loop=loop)\n        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(\n            SimpleCookie\n        )\n        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (\n            defaultdict(dict)\n        )\n        self._host_only_cookies: Set[Tuple[str, str]] = set()\n        self._unsafe = unsafe\n        self._quote_cookie = quote_cookie\n        if treat_as_secure_origin is None:\n            treat_as_secure_origin = []\n        elif isinstance(treat_as_secure_origin, URL):\n            treat_as_secure_origin = [treat_as_secure_origin.origin()]\n        elif isinstance(treat_as_secure_origin, str):\n            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]\n        else:\n            treat_as_secure_origin = [\n                URL(url).origin() if isinstance(url, str) else url.origin()\n                for url in treat_as_secure_origin\n            ]\n        self._treat_as_secure_origin = treat_as_secure_origin\n        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []\n        self._expirations: Dict[Tuple[str, str, str], float] = {}\n\n    def save(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"wb\") as f:\n            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)\n\n    def load(self, file_path: PathLike) -> None:\n        file_path = pathlib.Path(file_path)\n        with file_path.open(mode=\"rb\") as f:\n            self._cookies = pickle.load(f)\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        if predicate is None:\n            self._expire_heap.clear()\n            self._cookies.clear()\n            self._morsel_cache.clear()\n            self._host_only_cookies.clear()\n            self._expirations.clear()\n            return\n\n        now = time.time()\n        to_del = [\n            key\n            for (domain, path), cookie in self._cookies.items()\n            for name, morsel in cookie.items()\n            if (\n                (key := (domain, path, name)) in self._expirations\n                and self._expirations[key] <= now\n            )\n            or predicate(morsel)\n        ]\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def clear_domain(self, domain: str) -> None:\n        self.clear(lambda x: self._is_domain_match(domain, x[\"domain\"]))\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        self._do_expiration()\n        for val in self._cookies.values():\n            yield from val.values()\n\n    def __len__(self) -> int:\n        \"\"\"Return number of cookies.\n\n        This function does not iterate self to avoid unnecessary expiration\n        checks.\n        \"\"\"\n        return sum(len(cookie.values()) for cookie in self._cookies.values())\n\n    def _do_expiration(self) -> None:\n        \"\"\"Remove expired cookies.\"\"\"\n        if not (expire_heap_len := len(self._expire_heap)):\n            return\n\n        # If the expiration heap grows larger than the number expirations\n        # times two, we clean it up to avoid keeping expired entries in\n        # the heap and consuming memory. We guard this with a minimum\n        # threshold to avoid cleaning up the heap too often when there are\n        # only a few scheduled expirations.\n        if (\n            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION\n            and expire_heap_len > len(self._expirations) * 2\n        ):\n            # Remove any expired entries from the expiration heap\n            # that do not match the expiration time in the expirations\n            # as it means the cookie has been re-added to the heap\n            # with a different expiration time.\n            self._expire_heap = [\n                entry\n                for entry in self._expire_heap\n                if self._expirations.get(entry[1]) == entry[0]\n            ]\n            heapq.heapify(self._expire_heap)\n\n        now = time.time()\n        to_del: List[Tuple[str, str, str]] = []\n        # Find any expired cookies and add them to the to-delete list\n        while self._expire_heap:\n            when, cookie_key = self._expire_heap[0]\n            if when > now:\n                break\n            heapq.heappop(self._expire_heap)\n            # Check if the cookie hasn't been re-added to the heap\n            # with a different expiration time as it will be removed\n            # later when it reaches the top of the heap and its\n            # expiration time is met.\n            if self._expirations.get(cookie_key) == when:\n                to_del.append(cookie_key)\n\n        if to_del:\n            self._delete_cookies(to_del)\n\n    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:\n        for domain, path, name in to_del:\n            self._host_only_cookies.discard((domain, name))\n            self._cookies[(domain, path)].pop(name, None)\n            self._morsel_cache[(domain, path)].pop(name, None)\n            self._expirations.pop((domain, path, name), None)\n\n    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:\n        cookie_key = (domain, path, name)\n        if self._expirations.get(cookie_key) == when:\n            # Avoid adding duplicates to the heap\n            return\n        heapq.heappush(self._expire_heap, (when, cookie_key))\n        self._expirations[cookie_key] = when\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        \"\"\"Update cookies.\"\"\"\n        hostname = response_url.raw_host\n\n        if not self._unsafe and is_ip_address(hostname):\n            # Don't accept cookies from IPs\n            return\n\n        if isinstance(cookies, Mapping):\n            cookies = cookies.items()\n\n        for name, cookie in cookies:\n            if not isinstance(cookie, Morsel):\n                tmp = SimpleCookie()\n                tmp[name] = cookie  # type: ignore[assignment]\n                cookie = tmp[name]\n\n            domain = cookie[\"domain\"]\n\n            # ignore domains with trailing dots\n            if domain and domain[-1] == \".\":\n                domain = \"\"\n                del cookie[\"domain\"]\n\n            if not domain and hostname is not None:\n                # Set the cookie's domain to the response hostname\n                # and set its host-only-flag\n                self._host_only_cookies.add((hostname, name))\n                domain = cookie[\"domain\"] = hostname\n\n            if domain and domain[0] == \".\":\n                # Remove leading dot\n                domain = domain[1:]\n                cookie[\"domain\"] = domain\n\n            if hostname and not self._is_domain_match(domain, hostname):\n                # Setting cookies for different domains is not allowed\n                continue\n\n            path = cookie[\"path\"]\n            if not path or path[0] != \"/\":\n                # Set the cookie's path to the response path\n                path = response_url.path\n                if not path.startswith(\"/\"):\n                    path = \"/\"\n                else:\n                    # Cut everything from the last slash to the end\n                    path = \"/\" + path[1 : path.rfind(\"/\")]\n                cookie[\"path\"] = path\n            path = path.rstrip(\"/\")\n\n            if max_age := cookie[\"max-age\"]:\n                try:\n                    delta_seconds = int(max_age)\n                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)\n                    self._expire_cookie(max_age_expiration, domain, path, name)\n                except ValueError:\n                    cookie[\"max-age\"] = \"\"\n\n            elif expires := cookie[\"expires\"]:\n                if expire_time := self._parse_date(expires):\n                    self._expire_cookie(expire_time, domain, path, name)\n                else:\n                    cookie[\"expires\"] = \"\"\n\n            key = (domain, path)\n            if self._cookies[key].get(name) != cookie:\n                # Don't blow away the cache if the same\n                # cookie gets set again\n                self._cookies[key][name] = cookie\n                self._morsel_cache[key].pop(name, None)\n\n        self._do_expiration()\n\n    def filter_cookies(self, request_url: URL = URL()) -> \"BaseCookie[str]\":\n        \"\"\"Returns this jar's cookies filtered by their attributes.\"\"\"\n        filtered: Union[SimpleCookie, \"BaseCookie[str]\"] = (\n            SimpleCookie() if self._quote_cookie else BaseCookie()\n        )\n        if not self._cookies:\n            # Skip do_expiration() if there are no cookies.\n            return filtered\n        self._do_expiration()\n        if not self._cookies:\n            # Skip rest of function if no non-expired cookies.\n            return filtered\n        request_url = URL(request_url)\n        hostname = request_url.raw_host or \"\"\n\n        is_not_secure = request_url.scheme not in (\"https\", \"wss\")\n        if is_not_secure and self._treat_as_secure_origin:\n            request_origin = URL()\n            with contextlib.suppress(ValueError):\n                request_origin = request_url.origin()\n            is_not_secure = request_origin not in self._treat_as_secure_origin\n\n        # Send shared cookie\n        for c in self._cookies[(\"\", \"\")].values():\n            filtered[c.key] = c.value\n\n        if is_ip_address(hostname):\n            if not self._unsafe:\n                return filtered\n            domains: Iterable[str] = (hostname,)\n        else:\n            # Get all the subdomains that might match a cookie (e.g. \"foo.bar.com\", \"bar.com\", \"com\")\n            domains = itertools.accumulate(\n                reversed(hostname.split(\".\")), _FORMAT_DOMAIN_REVERSED\n            )\n\n        # Get all the path prefixes that might match a cookie (e.g. \"\", \"/foo\", \"/foo/bar\")\n        paths = itertools.accumulate(request_url.path.split(\"/\"), _FORMAT_PATH)\n        # Create every combination of (domain, path) pairs.\n        pairs = itertools.product(domains, paths)\n\n        path_len = len(request_url.path)\n        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4\n        for p in pairs:\n            for name, cookie in self._cookies[p].items():\n                domain = cookie[\"domain\"]\n\n                if (domain, name) in self._host_only_cookies and domain != hostname:\n                    continue\n\n                # Skip edge case when the cookie has a trailing slash but request doesn't.\n                if len(cookie[\"path\"]) > path_len:\n                    continue\n\n                if is_not_secure and cookie[\"secure\"]:\n                    continue\n\n                # We already built the Morsel so reuse it here\n                if name in self._morsel_cache[p]:\n                    filtered[name] = self._morsel_cache[p][name]\n                    continue\n\n                # It's critical we use the Morsel so the coded_value\n                # (based on cookie version) is preserved\n                mrsl_val = cast(\"Morsel[str]\", cookie.get(cookie.key, Morsel()))\n                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)\n                self._morsel_cache[p][name] = mrsl_val\n                filtered[name] = mrsl_val\n\n        return filtered\n\n    @staticmethod\n    def _is_domain_match(domain: str, hostname: str) -> bool:\n        \"\"\"Implements domain matching adhering to RFC 6265.\"\"\"\n        if hostname == domain:\n            return True\n\n        if not hostname.endswith(domain):\n            return False\n\n        non_matching = hostname[: -len(domain)]\n\n        if not non_matching.endswith(\".\"):\n            return False\n\n        return not is_ip_address(hostname)\n\n    @classmethod\n    def _parse_date(cls, date_str: str) -> Optional[int]:\n        \"\"\"Implements date string parsing adhering to RFC 6265.\"\"\"\n        if not date_str:\n            return None\n\n        found_time = False\n        found_day = False\n        found_month = False\n        found_year = False\n\n        hour = minute = second = 0\n        day = 0\n        month = 0\n        year = 0\n\n        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):\n\n            token = token_match.group(\"token\")\n\n            if not found_time:\n                time_match = cls.DATE_HMS_TIME_RE.match(token)\n                if time_match:\n                    found_time = True\n                    hour, minute, second = (int(s) for s in time_match.groups())\n                    continue\n\n            if not found_day:\n                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)\n                if day_match:\n                    found_day = True\n                    day = int(day_match.group())\n                    continue\n\n            if not found_month:\n                month_match = cls.DATE_MONTH_RE.match(token)\n                if month_match:\n                    found_month = True\n                    assert month_match.lastindex is not None\n                    month = month_match.lastindex\n                    continue\n\n            if not found_year:\n                year_match = cls.DATE_YEAR_RE.match(token)\n                if year_match:\n                    found_year = True\n                    year = int(year_match.group())\n\n        if 70 <= year <= 99:\n            year += 1900\n        elif 0 <= year <= 69:\n            year += 2000\n\n        if False in (found_day, found_month, found_year, found_time):\n            return None\n\n        if not 1 <= day <= 31:\n            return None\n\n        if year < 1601 or hour > 23 or minute > 59 or second > 59:\n            return None\n\n        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))\n\n\nclass DummyCookieJar(AbstractCookieJar):\n    \"\"\"Implements a dummy cookie storage.\n\n    It can be used with the ClientSession when no cookie processing is needed.\n\n    \"\"\"\n\n    def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:\n        super().__init__(loop=loop)\n\n    def __iter__(self) -> \"Iterator[Morsel[str]]\":\n        while False:\n            yield None\n\n    def __len__(self) -> int:\n        return 0\n\n    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:\n        pass\n\n    def clear_domain(self, domain: str) -> None:\n        pass\n\n    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:\n        pass\n\n    def filter_cookies(self, request_url: URL) -> \"BaseCookie[str]\":\n        return SimpleCookie()\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** `filter_cookies` Does Not Emit DeprecationWarning When Called with a String URL

**Description:**

When using the `filter_cookies` method of `CookieJar`, passing a URL as a string does not trigger a `DeprecationWarning` as expected. This behavior deviates from the intended functionality where only `URL` instances should be used, and passing a string should warn developers about the upcoming change.

**Example Code:**

```python
jar = CookieJar()
jar.update_cookies(SimpleCookie("shared-cookie=first; Domain=example.com;"))
jar.filter_cookies("http://éé.com")
```

**Expected Behavior:**

Calling `filter_cookies` with a string URL should emit a `DeprecationWarning` indicating that a `URL` instance is expected. This warning helps developers transition to using `URL` instances before future versions enforce this requirement.

**Actual Behavior:**

No `DeprecationWarning` is emitted when `filter_cookies` is called with a string URL. As a result, developers might be unaware of the need to update their code, leading to potential issues in future releases.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/cookiejar.py
import asyncio
import calendar
import contextlib
import datetime
import heapq
import itertools
import os  # noqa
import pathlib
import pickle
import re
import time
from collections import defaultdict
from http.cookies import BaseCookie, Morsel, SimpleCookie
from typing import (
    DefaultDict,
    Dict,
    Iterable,
    Iterator,
    List,
    Mapping,
    Optional,
    Set,
    Tuple,
    Union,
    cast,
)

from yarl import URL

from .abc import AbstractCookieJar, ClearCookiePredicate
from .helpers import is_ip_address
from .typedefs import LooseCookies, PathLike, StrOrURL

__all__ = ("CookieJar", "DummyCookieJar")


CookieItem = Union[str, "Morsel[str]"]

# We cache these string methods here as their use is in performance critical code.
_FORMAT_PATH = "{}/{}".format
_FORMAT_DOMAIN_REVERSED = "{1}.{0}".format

# The minimum number of scheduled cookie expirations before we start cleaning up
# the expiration heap. This is a performance optimization to avoid cleaning up the
# heap too often when there are only a few scheduled expirations.
_MIN_SCHEDULED_COOKIE_EXPIRATION = 100


class CookieJar(AbstractCookieJar):
    """Implements cookie storage adhering to RFC 6265."""

    DATE_TOKENS_RE = re.compile(
        r"[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]*"
        r"(?P<token>[\x00-\x08\x0A-\x1F\d:a-zA-Z\x7F-\xFF]+)"
    )

    DATE_HMS_TIME_RE = re.compile(r"(\d{1,2}):(\d{1,2}):(\d{1,2})")

    DATE_DAY_OF_MONTH_RE = re.compile(r"(\d{1,2})")

    DATE_MONTH_RE = re.compile(
        "(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)",
        re.I,
    )

    DATE_YEAR_RE = re.compile(r"(\d{2,4})")

    # calendar.timegm() fails for timestamps after datetime.datetime.max
    # Minus one as a loss of precision occurs when timestamp() is called.
    MAX_TIME = (
        int(datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()) - 1
    )
    try:
        calendar.timegm(time.gmtime(MAX_TIME))
    except (OSError, ValueError):
        # Hit the maximum representable time on Windows
        # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64
        # Throws ValueError on PyPy 3.9, OSError elsewhere
        MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1))
    except OverflowError:
        # #4515: datetime.max may not be representable on 32-bit platforms
        MAX_TIME = 2**31 - 1
    # Avoid minuses in the future, 3x faster
    SUB_MAX_TIME = MAX_TIME - 1

    def __init__(
        self,
        *,
        unsafe: bool = False,
        quote_cookie: bool = True,
        treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None,
        loop: Optional[asyncio.AbstractEventLoop] = None,
    ) -> None:
        super().__init__(loop=loop)
        self._cookies: DefaultDict[Tuple[str, str], SimpleCookie] = defaultdict(
            SimpleCookie
        )
        self._morsel_cache: DefaultDict[Tuple[str, str], Dict[str, Morsel[str]]] = (
            defaultdict(dict)
        )
        self._host_only_cookies: Set[Tuple[str, str]] = set()
        self._unsafe = unsafe
        self._quote_cookie = quote_cookie
        if treat_as_secure_origin is None:
            treat_as_secure_origin = []
        elif isinstance(treat_as_secure_origin, URL):
            treat_as_secure_origin = [treat_as_secure_origin.origin()]
        elif isinstance(treat_as_secure_origin, str):
            treat_as_secure_origin = [URL(treat_as_secure_origin).origin()]
        else:
            treat_as_secure_origin = [
                URL(url).origin() if isinstance(url, str) else url.origin()
                for url in treat_as_secure_origin
            ]
        self._treat_as_secure_origin = treat_as_secure_origin
        self._expire_heap: List[Tuple[float, Tuple[str, str, str]]] = []
        self._expirations: Dict[Tuple[str, str, str], float] = {}

    def save(self, file_path: PathLike) -> None:
        file_path = pathlib.Path(file_path)
        with file_path.open(mode="wb") as f:
            pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL)

    def load(self, file_path: PathLike) -> None:
        file_path = pathlib.Path(file_path)
        with file_path.open(mode="rb") as f:
            self._cookies = pickle.load(f)

    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
        if predicate is None:
            self._expire_heap.clear()
            self._cookies.clear()
            self._morsel_cache.clear()
            self._host_only_cookies.clear()
            self._expirations.clear()
            return

        now = time.time()
        to_del = [
            key
            for (domain, path), cookie in self._cookies.items()
            for name, morsel in cookie.items()
            if (
                (key := (domain, path, name)) in self._expirations
                and self._expirations[key] <= now
            )
            or predicate(morsel)
        ]
        if to_del:
            self._delete_cookies(to_del)

    def clear_domain(self, domain: str) -> None:
        self.clear(lambda x: self._is_domain_match(domain, x["domain"]))

    def __iter__(self) -> "Iterator[Morsel[str]]":
        self._do_expiration()
        for val in self._cookies.values():
            yield from val.values()

    def __len__(self) -> int:
        """Return number of cookies.

        This function does not iterate self to avoid unnecessary expiration
        checks.
        """
        return sum(len(cookie.values()) for cookie in self._cookies.values())

    def _do_expiration(self) -> None:
        """Remove expired cookies."""
        if not (expire_heap_len := len(self._expire_heap)):
            return

        # If the expiration heap grows larger than the number expirations
        # times two, we clean it up to avoid keeping expired entries in
        # the heap and consuming memory. We guard this with a minimum
        # threshold to avoid cleaning up the heap too often when there are
        # only a few scheduled expirations.
        if (
            expire_heap_len > _MIN_SCHEDULED_COOKIE_EXPIRATION
            and expire_heap_len > len(self._expirations) * 2
        ):
            # Remove any expired entries from the expiration heap
            # that do not match the expiration time in the expirations
            # as it means the cookie has been re-added to the heap
            # with a different expiration time.
            self._expire_heap = [
                entry
                for entry in self._expire_heap
                if self._expirations.get(entry[1]) == entry[0]
            ]
            heapq.heapify(self._expire_heap)

        now = time.time()
        to_del: List[Tuple[str, str, str]] = []
        # Find any expired cookies and add them to the to-delete list
        while self._expire_heap:
            when, cookie_key = self._expire_heap[0]
            if when > now:
                break
            heapq.heappop(self._expire_heap)
            # Check if the cookie hasn't been re-added to the heap
            # with a different expiration time as it will be removed
            # later when it reaches the top of the heap and its
            # expiration time is met.
            if self._expirations.get(cookie_key) == when:
                to_del.append(cookie_key)

        if to_del:
            self._delete_cookies(to_del)

    def _delete_cookies(self, to_del: List[Tuple[str, str, str]]) -> None:
        for domain, path, name in to_del:
            self._host_only_cookies.discard((domain, name))
            self._cookies[(domain, path)].pop(name, None)
            self._morsel_cache[(domain, path)].pop(name, None)
            self._expirations.pop((domain, path, name), None)

    def _expire_cookie(self, when: float, domain: str, path: str, name: str) -> None:
        cookie_key = (domain, path, name)
        if self._expirations.get(cookie_key) == when:
            # Avoid adding duplicates to the heap
            return
        heapq.heappush(self._expire_heap, (when, cookie_key))
        self._expirations[cookie_key] = when

    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
        """Update cookies."""
        hostname = response_url.raw_host

        if not self._unsafe and is_ip_address(hostname):
            # Don't accept cookies from IPs
            return

        if isinstance(cookies, Mapping):
            cookies = cookies.items()

        for name, cookie in cookies:
            if not isinstance(cookie, Morsel):
                tmp = SimpleCookie()
                tmp[name] = cookie  # type: ignore[assignment]
                cookie = tmp[name]

            domain = cookie["domain"]

            # ignore domains with trailing dots
            if domain and domain[-1] == ".":
                domain = ""
                del cookie["domain"]

            if not domain and hostname is not None:
                # Set the cookie's domain to the response hostname
                # and set its host-only-flag
                self._host_only_cookies.add((hostname, name))
                domain = cookie["domain"] = hostname

            if domain and domain[0] == ".":
                # Remove leading dot
                domain = domain[1:]
                cookie["domain"] = domain

            if hostname and not self._is_domain_match(domain, hostname):
                # Setting cookies for different domains is not allowed
                continue

            path = cookie["path"]
            if not path or path[0] != "/":
                # Set the cookie's path to the response path
                path = response_url.path
                if not path.startswith("/"):
                    path = "/"
                else:
                    # Cut everything from the last slash to the end
                    path = "/" + path[1 : path.rfind("/")]
                cookie["path"] = path
            path = path.rstrip("/")

            if max_age := cookie["max-age"]:
                try:
                    delta_seconds = int(max_age)
                    max_age_expiration = min(time.time() + delta_seconds, self.MAX_TIME)
                    self._expire_cookie(max_age_expiration, domain, path, name)
                except ValueError:
                    cookie["max-age"] = ""

            elif expires := cookie["expires"]:
                if expire_time := self._parse_date(expires):
                    self._expire_cookie(expire_time, domain, path, name)
                else:
                    cookie["expires"] = ""

            key = (domain, path)
            if self._cookies[key].get(name) != cookie:
                # Don't blow away the cache if the same
                # cookie gets set again
                self._cookies[key][name] = cookie
                self._morsel_cache[key].pop(name, None)

        self._do_expiration()

    def filter_cookies(self, request_url: URL = URL()) -> "BaseCookie[str]":
        """Returns this jar's cookies filtered by their attributes."""
        filtered: Union[SimpleCookie, "BaseCookie[str]"] = (
            SimpleCookie() if self._quote_cookie else BaseCookie()
        )
        if not self._cookies:
            # Skip do_expiration() if there are no cookies.
            return filtered
        self._do_expiration()
        if not self._cookies:
            # Skip rest of function if no non-expired cookies.
            return filtered
        request_url = URL(request_url)
        hostname = request_url.raw_host or ""

        is_not_secure = request_url.scheme not in ("https", "wss")
        if is_not_secure and self._treat_as_secure_origin:
            request_origin = URL()
            with contextlib.suppress(ValueError):
                request_origin = request_url.origin()
            is_not_secure = request_origin not in self._treat_as_secure_origin

        # Send shared cookie
        for c in self._cookies[("", "")].values():
            filtered[c.key] = c.value

        if is_ip_address(hostname):
            if not self._unsafe:
                return filtered
            domains: Iterable[str] = (hostname,)
        else:
            # Get all the subdomains that might match a cookie (e.g. "foo.bar.com", "bar.com", "com")
            domains = itertools.accumulate(
                reversed(hostname.split(".")), _FORMAT_DOMAIN_REVERSED
            )

        # Get all the path prefixes that might match a cookie (e.g. "", "/foo", "/foo/bar")
        paths = itertools.accumulate(request_url.path.split("/"), _FORMAT_PATH)
        # Create every combination of (domain, path) pairs.
        pairs = itertools.product(domains, paths)

        path_len = len(request_url.path)
        # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4
        for p in pairs:
            for name, cookie in self._cookies[p].items():
                domain = cookie["domain"]

                if (domain, name) in self._host_only_cookies and domain != hostname:
                    continue

                # Skip edge case when the cookie has a trailing slash but request doesn't.
                if len(cookie["path"]) > path_len:
                    continue

                if is_not_secure and cookie["secure"]:
                    continue

                # We already built the Morsel so reuse it here
                if name in self._morsel_cache[p]:
                    filtered[name] = self._morsel_cache[p][name]
                    continue

                # It's critical we use the Morsel so the coded_value
                # (based on cookie version) is preserved
                mrsl_val = cast("Morsel[str]", cookie.get(cookie.key, Morsel()))
                mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)
                self._morsel_cache[p][name] = mrsl_val
                filtered[name] = mrsl_val

        return filtered

    @staticmethod
    def _is_domain_match(domain: str, hostname: str) -> bool:
        """Implements domain matching adhering to RFC 6265."""
        if hostname == domain:
            return True

        if not hostname.endswith(domain):
            return False

        non_matching = hostname[: -len(domain)]

        if not non_matching.endswith("."):
            return False

        return not is_ip_address(hostname)

    @classmethod
    def _parse_date(cls, date_str: str) -> Optional[int]:
        """Implements date string parsing adhering to RFC 6265."""
        if not date_str:
            return None

        found_time = False
        found_day = False
        found_month = False
        found_year = False

        hour = minute = second = 0
        day = 0
        month = 0
        year = 0

        for token_match in cls.DATE_TOKENS_RE.finditer(date_str):

            token = token_match.group("token")

            if not found_time:
                time_match = cls.DATE_HMS_TIME_RE.match(token)
                if time_match:
                    found_time = True
                    hour, minute, second = (int(s) for s in time_match.groups())
                    continue

            if not found_day:
                day_match = cls.DATE_DAY_OF_MONTH_RE.match(token)
                if day_match:
                    found_day = True
                    day = int(day_match.group())
                    continue

            if not found_month:
                month_match = cls.DATE_MONTH_RE.match(token)
                if month_match:
                    found_month = True
                    assert month_match.lastindex is not None
                    month = month_match.lastindex
                    continue

            if not found_year:
                year_match = cls.DATE_YEAR_RE.match(token)
                if year_match:
                    found_year = True
                    year = int(year_match.group())

        if 70 <= year <= 99:
            year += 1900
        elif 0 <= year <= 69:
            year += 2000

        if False in (found_day, found_month, found_year, found_time):
            return None

        if not 1 <= day <= 31:
            return None

        if year < 1601 or hour > 23 or minute > 59 or second > 59:
            return None

        return calendar.timegm((year, month, day, hour, minute, second, -1, -1, -1))


class DummyCookieJar(AbstractCookieJar):
    """Implements a dummy cookie storage.

    It can be used with the ClientSession when no cookie processing is needed.

    """

    def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:
        super().__init__(loop=loop)

    def __iter__(self) -> "Iterator[Morsel[str]]":
        while False:
            yield None

    def __len__(self) -> int:
        return 0

    def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
        pass

    def clear_domain(self, domain: str) -> None:
        pass

    def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
        pass

    def filter_cookies(self, request_url: URL) -> "BaseCookie[str]":
        return SimpleCookie()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user