Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l97LB-0001bY-Tz for psycopg@arkaria.postgresql.org; Mon, 08 Feb 2021 14:16:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1l97L9-0003Ya-Kt for psycopg@arkaria.postgresql.org; Mon, 08 Feb 2021 14:16:35 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l97L9-0003YT-A7 for psycopg@lists.postgresql.org; Mon, 08 Feb 2021 14:16:35 +0000 Received: from mail1.dalibo.net ([212.83.143.11] helo=mail.dalibo.com) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1l97L4-0003Zf-Uc for psycopg@postgresql.org; Mon, 08 Feb 2021 14:16:34 +0000 Received: from [192.168.0.29] (lan31-5-82-234-69-236.fbx.proxad.net [82.234.69.236]) by mail.dalibo.com (Postfix) with ESMTPSA id EE9AA1F9E6; Mon, 8 Feb 2021 15:16:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=dalibo.com; s=a; t=1612793788; bh=8gUtf+D5JsuNgi8rReIWWiwCd5MiFHsQPjIIdNB/AO0=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=OI7rVAy4CgX/4vyrdmiQdFwz4JPh7YiUjvobkLXtx/CubXwzN0kjwpVKFMpNuDSJg /bI/9XWvsaHUp0huTxDEzqSaYkkgzUAfRDHu7z66EKoAR3rPClcFVuW/1KnBFE/7Lv hXdBscA5+9AoaH+SRNYPggFGBX8zBhGUKXmc5ZWk= Subject: Re: Latest developments in psycopg3 To: Daniele Varrazzo Cc: psycopg@postgresql.org References: <4eb4e86a-c813-bb8f-ae93-4f1b9fd46b6b@dalibo.com> From: Denis Laxalde Message-ID: Date: Mon, 8 Feb 2021 15:16:27 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Daniele Varrazzo a écrit : > On Mon, 8 Feb 2021 at 12:14, Denis Laxalde wrote: >> - It seems to me that the conn-info developments work fine (also looked >> at the commits, which look fine as well to me): what needs to be done >> here? Any help needed? > > I can't remember what is missing: probably the interface is complete, > it is missing test coverage and documentation. I will review if there > are methods missing: its purpose is to expose pretty much all the info > about the connection that the libpq can give, correctly decoded from > bytes. Complete tests and docs are definitely to be added. Ok, good to know. (Let me know if help is needed.) >> - There appears to be no card about dictcursor on the project board. >> What's the plan (and priority) for that (if any)? > > I forgot to add a point about them, sorry: I added one now. There is > no firm plan for me, but probably a conversation to have, because I > have my own usage patterns for psycopg2, when I am its user, and I > want to be mindful of other use cases too. > > In short: yes, I would like to provide alternative record factories. > We can review if the best way is to create cursor subclasses > out-of-the-box or mixins. In psycopg2 there are: > > - DictCursor (returns a hybrid object between a sequence and a dictionary) > - RealDictCursor (returns a straight subclass of a dictionary, so it's > not a legit dbapi cursor as it doesn't expose a sequence) > - NamedTupleCursor (what it says on the tin). > > Personally I use the NamedTupeCursor most often, as I prefer the dot > notation to access attribute. Named tuples also have a _dict() method > when a dict is needed. If psycopg3 was only my pet project, I would > personally have NamedTuples as the default and only thing supported... > But that's hardly the case. Personally, I use DictCursor because it provides access to rows without depending on SELECT order and then pass items to a custom dataclass as **kwargs. > 1) We can provide a feature to select the type of cursor that is not > much dissimilar from psycopg2 > 2) Do we need DictCursor/RealDictCursor? ISTM that one of the two > would be sufficient? Possibly an object inheriting from a Python dict > instead of emulating it so that e.g. json.dumps() Inheriting from dict is strange because we only need read access. So rather collections.abc.Mapping, I think. > 3) Or, conversely, we could have a Row object providing both attribute > and getattr access, both as index and name: > > row.myattr > row["myattr"] > row[1] +1 (this would also fit with collections.abc.Mapping) > > 4) There are reports of the *DictCursor being slow: the objects in > psycopg2 have hardly been profiled. I would look well at the > performance of the objects created. > > I am curious about why people use DictCursor: what are its advantages? > Should we provide such objects only to guarantee a smoother upgrade > path or there are use cases where they are genuinely better than > NamedTuples or a would-be Row object (JSON does come to mind). I seem to recall that namedtuple was not good for performances as either (see this article https://lwn.net/Articles/731423/ for instance). I tend to avoid using them and often write custom classes instead (which is very handy with py3.7's dataclass). So, for me, no use case that wouldn't be covered by "would-be Row object". >> I'm also curious about the "strictly typed" thing you wrote above. What >> do you have in mind more specifically? > > The codebase uses mypy --strict, so it is extensively type-annotated > and of course all the public interfaces are type-annotated too, to > collaborate with projects using static typing. I am also curious about > whether it would be possible to provide types out of the query > results, but I doubt it is. That does not sounds feasible/easy. It's the price to pay where interfacing with external data sources (e.g. the same is true when one retrieves data from a JSON API) and type checking is probably only possible when "decoding" results. > Which makes me think... 5) PydanticCursor? Or, as a more general case, > implement all the cursor flavours not as subclasses but using a > rowfactory function, and allow people to use their own (e.g. asking a > cursor to create a Pydantic model provided by the user, so that they > can have psycopg3 collaborate with e.g. FastAPI strictly typed > models). Or a Python dataclass... Providing a plugable API for that would be really nice, indeed.