git: a94b51d40765 - main - www/py-binarycookies: new port had been added (+)

From: Alexey Dokuchaev <danfe_at_FreeBSD.org>
Date: Wed, 25 Jun 2025 16:25:37 UTC
The branch main has been updated by danfe:

URL: https://cgit.FreeBSD.org/ports/commit/?id=a94b51d40765f0aedfca0069940d14db5068640e

commit a94b51d40765f0aedfca0069940d14db5068640e
Author:     Alexey Dokuchaev <danfe@FreeBSD.org>
AuthorDate: 2025-06-25 16:22:30 +0000
Commit:     Alexey Dokuchaev <danfe@FreeBSD.org>
CommitDate: 2025-06-25 16:22:30 +0000

    www/py-binarycookies: new port had been added (+)
    
    Apple's Safari web browser binary cookies format (de)serializer
    written in Python.  Our modifications to the original sources
    include the fix for "the year 2038 problem" on 32-bit systems,
    Netscape traditional `cookies.txt' file format support, and use
    of Pydantic V1 which does not pull in Rust unlike V2 which the
    project needlessly assumes by default.
---
 www/Makefile                                       |  1 +
 www/py-binarycookies/Makefile                      | 26 ++++++++++++
 www/py-binarycookies/distinfo                      |  3 ++
 .../files/patch-src_binarycookies_____main____.py  | 49 ++++++++++++++++++++++
 .../files/patch-src_binarycookies___deserialize.py | 21 ++++++++++
 www/py-binarycookies/pkg-descr                     |  6 +++
 6 files changed, 106 insertions(+)

diff --git a/www/Makefile b/www/Makefile
index 320f82474594..e72084fbdc21 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -1487,6 +1487,7 @@
     SUBDIR += py-beaker
     SUBDIR += py-beautifulsoup
     SUBDIR += py-betamax
+    SUBDIR += py-binarycookies
     SUBDIR += py-biscuits
     SUBDIR += py-bjoern
     SUBDIR += py-bleach
diff --git a/www/py-binarycookies/Makefile b/www/py-binarycookies/Makefile
new file mode 100644
index 000000000000..4a76b5bfd247
--- /dev/null
+++ b/www/py-binarycookies/Makefile
@@ -0,0 +1,26 @@
+PORTNAME=	binarycookies
+PORTVERSION=	2.1.5
+CATEGORIES=	www python
+MASTER_SITES=	PYPI
+PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
+
+MAINTAINER=	danfe@FreeBSD.org
+COMMENT=	Binary cookies (de)serializer written in Python
+WWW=		https://pypi.org/project/binarycookies/
+
+LICENSE=	MIT
+
+RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}pydantic>=0:devel/py-pydantic@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}typer>=0.12.3:devel/py-typer@${PY_FLAVOR}
+
+USES=		python
+USE_PYTHON=	autoplist distutils
+
+NO_ARCH=	yes
+
+post-patch:
+# Do not pick up leftovers (*.orig files etc.) when making the package
+	@${REINPLACE_CMD} -e '/^package_data =/,+1s,\*,&.py,' \
+		${WRKSRC}/${PYSETUP}
+
+.include <bsd.port.mk>
diff --git a/www/py-binarycookies/distinfo b/www/py-binarycookies/distinfo
new file mode 100644
index 000000000000..90ad5f5508ac
--- /dev/null
+++ b/www/py-binarycookies/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1744141848
+SHA256 (binarycookies-2.1.5.tar.gz) = ff28a8e90e6ba02bc82fb2ff0d1d9a4a3be1ee9289a58f74a653d264928a31f3
+SIZE (binarycookies-2.1.5.tar.gz) = 8448
diff --git a/www/py-binarycookies/files/patch-src_binarycookies_____main____.py b/www/py-binarycookies/files/patch-src_binarycookies_____main____.py
new file mode 100644
index 000000000000..da43dac8dabd
--- /dev/null
+++ b/www/py-binarycookies/files/patch-src_binarycookies_____main____.py
@@ -0,0 +1,49 @@
+--- src/binarycookies/__main__.py.orig	2025-04-08 19:50:17 UTC
++++ src/binarycookies/__main__.py
+@@ -5,6 +5,8 @@ from sys import stdout
+ from typing import Type
+ 
+ import typer
++# https://github.com/Textualize/rich/issues/271
++println = print
+ from rich import print
+ 
+ from binarycookies import load
+@@ -20,6 +22,7 @@ class DateTimeEncoder(json.JSONEncoder):
+ class OutputType(str, Enum):
+     json = "json"
+     ascii = "ascii"
++    netscape = "netscape"
+ 
+ 
+ def cli(file_path: str, output: str = "json"):
+@@ -27,7 +30,7 @@ def cli(file_path: str, output: str = "json"):
+     with open(file_path, "rb") as f:
+         cookies = load(f)
+     if output == OutputType.json:
+-        json.dump([cookie.model_dump() for cookie in cookies], indent=2, cls=DateTimeEncoder, fp=stdout)
++        json.dump([cookie.dict() for cookie in cookies], indent=2, cls=DateTimeEncoder, fp=stdout)
+     elif output == OutputType.ascii:
+         for cookie in cookies:
+             print(f"Name: {cookie.name}")
+@@ -38,6 +41,20 @@ def cli(file_path: str, output: str = "json"):
+             print(f"Expires: {cookie.expiry_datetime.isoformat()}")
+             print(f"Flag: {cookie.flag.value}")
+             print("-" * 40)
++    elif output == OutputType.netscape:
++        # http://www.cookiecentral.com/faq/#3.5
++        println("# Netscape HTTP Cookie File")
++        for cookie in cookies:
++            println("%(domain)s\t%(flag)s\t%(path)s\t%(secure)s\t%(expiry)d\t%(name)s\t%(value)s" % dict(
++              domain = cookie.url,
++              flag = str(cookie.url.startswith('.')).upper(),
++              path = cookie.path,
++              secure = str('Secure' in cookie.flag.value).upper(),
++              expiry = cookie.expiry_datetime.timestamp(),
++              name = cookie.name,
++              value = cookie.value))
++    else:
++            print(f"Unsupported output format, can only do {', '.join('[green]%s[/green]' % ot.name for ot in OutputType)}.")
+ 
+ 
+ def main():
diff --git a/www/py-binarycookies/files/patch-src_binarycookies___deserialize.py b/www/py-binarycookies/files/patch-src_binarycookies___deserialize.py
new file mode 100644
index 000000000000..3aec2539907c
--- /dev/null
+++ b/www/py-binarycookies/files/patch-src_binarycookies___deserialize.py
@@ -0,0 +1,21 @@
+--- src/binarycookies/_deserialize.py.orig	2025-04-08 19:50:17 UTC
++++ src/binarycookies/_deserialize.py
+@@ -1,6 +1,7 @@
+ from datetime import datetime, timezone
+ from io import BytesIO
+ from struct import unpack
++from sys import maxsize
+ from typing import BinaryIO, List, Union
+ 
+ from binarycookies.models import (
+@@ -28,7 +29,9 @@ def interpret_flag(flags: int) -> Flag:
+ 
+ def mac_epoch_to_date(epoch: int) -> datetime:
+     """Converts a mac epoch time to a datetime object."""
+-    return datetime.fromtimestamp(epoch + 978307200, tz=timezone.utc)
++    unix_epoch = epoch + 978307200
++    if unix_epoch > maxsize: unix_epoch = maxsize
++    return datetime.fromtimestamp(unix_epoch, tz=timezone.utc)
+ 
+ 
+ def read_string(data: BytesIO, size: int) -> str:
diff --git a/www/py-binarycookies/pkg-descr b/www/py-binarycookies/pkg-descr
new file mode 100644
index 000000000000..e53f18a363c9
--- /dev/null
+++ b/www/py-binarycookies/pkg-descr
@@ -0,0 +1,6 @@
+Python library and command-line tool for reading and writing binary
+cookies files used by Apple's Safari web browser on macOS and iOS.
+
+The `bcparser' program supports three output types: JSON (default),
+ASCII (line-by-line text format), and Netscape legacy `cookies.txt'
+format used by popular tools such as curl, wget, yt-dlp, and others.