Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #91178

Re: Camelot a good tool for me

Path csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed2.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail
Return-Path <python-python-list@m.gmane.org>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.000
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'encoded': 0.05; 'that?': 0.05; 'stack.': 0.07; 'table.': 0.07; 'backwards': 0.09; 'committing': 0.09; 'iterate': 0.09; 'optional': 0.09; 'orm': 0.09; 'received:151': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'stating': 0.09; 'subtle': 0.09; 'tasks,': 0.09; 'underlying': 0.09; 'violates': 0.09; 'wrong,': 0.09; 'example:': 0.11; 'itself.': 0.11; 'exception': 0.13; 'syntax': 0.13; 'do,': 0.15; 'obviously': 0.15; 'skip:p 40': 0.15; "'');": 0.16; '23,': 0.16; 'api,': 0.16; "can't.": 0.16; 'code?': 0.16; 'conn,': 0.16; 'correctness': 0.16; 'happily': 0.16; 'iterating': 0.16; 'magic': 0.16; 'middle,': 0.16; 'query,': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'row': 0.16; 'sequential': 0.16; 'someone,': 0.16; 'sqlalchemy': 0.16; 'sqlalchemy,': 0.16; 'table;': 0.16; 'uncommon': 0.16; 'worst': 0.16; 'developer': 0.16; 'wrote:': 0.16; 'else,': 0.18; 'integer': 0.18; '>>>': 0.20; 'saying': 0.22; 'enforce': 0.22; 'exists.': 0.22; 'explicit': 0.22; 'junior': 0.22; 'level,': 0.22; 'strict': 0.22; 'users,': 0.22; 'am,': 0.23; 'code.': 0.23; 'bit': 0.23; '2015': 0.23; 'consistent': 0.23; 'references': 0.23; 'sat,': 0.23; 'tables': 0.23; 'this:': 0.23; "haven't": 0.24; 'import': 0.24; 'implemented': 0.24; 'written': 0.24; 'header :User-Agent:1': 0.26; 'header:X-Complaints-To:1': 0.26; 'chris': 0.26; 'supported': 0.27; 'users.': 0.27; 'equivalent': 0.27; 'plain': 0.27; 'right.': 0.27; 'have,': 0.27; 'said,': 0.27; 'see,': 0.27; 'sequence': 0.27; 'went': 0.28; "i'm": 0.29; 'credentials': 0.29; 'declared': 0.29; 'equally': 0.29; 'key,': 0.29; 'parent': 0.29; 'pep': 0.29; 'second,': 0.29; 'table,': 0.29; 'no,': 0.29; '(which': 0.29; 'there.': 0.30; 'classes': 0.30; 'connection': 0.30; 'initially': 0.31; 'query': 0.31; 'task': 0.31; "i'd": 0.31; 'primary': 0.31; 'code': 0.31; 'run': 0.32; 'core': 0.32; 'implement': 0.32; 'says': 0.32; 'skip:p 30': 0.32; 'table': 0.32; 'probably': 0.32; 'possibly': 0.32; 'point': 0.33; 'class': 0.33; 'common': 0.33; 'usually': 0.33; 'picking': 0.33; 'surely': 0.33; 'foreign': 0.69; 'internet': 0.69; 'serial': 0.70; 'obvious': 0.72; 'construction': 0.73; 'upper': 0.76; 'saw': 0.76; 'paper': 0.78; 'low': 0.83; '(id': 0.84; 'back?': 0.84; 'child,': 0.84; "else's": 0.84; 'faster.': 0.84; 'fortunately,': 0.84; 'happened.': 0.84; 'order:': 0.84; 'quello': 0.84; 'subject:good': 0.84; 'subject:tool': 0.84; 'url:sqlalchemy': 0.84; 'approach.': 0.91; 'quando': 0.91; 'transactions': 0.91; 'url:core': 0.91; 'audit': 0.93; 'thing,': 0.93; 'imagine': 0.96
X-Injected-Via-Gmane http://gmane.org/
To python-list@python.org
From Lele Gaifax <lele@metapensiero.it>
Subject Re: Camelot a good tool for me
Date Sun, 24 May 2015 15:15:18 +0200
Organization Nautilus Entertainments
References <87zj4xoxfd.fsf@Equus.decebal.nl> <mjn804$4pe$1@dont-email.me> <87siaopxjs.fsf@Equus.decebal.nl> <201505221357.t4MDvgIV001904@fido.openend.se> <87k2w0le41.fsf@nautilus.nautilus> <CAPTjJmpnYwhOWdBz-=Zv8x+BO0G3e7OesPDvzd=nsX2a8Gsc-w@mail.gmail.com> <87fv6ol93p.fsf@nautilus.nautilus> <CAPTjJmoofyT1dWwoDBJWXtgs99cLiQQE-dvA1P7XJQvYxg5-sg@mail.gmail.com>
Mime-Version 1.0
Content-Type text/plain; charset=utf-8
Content-Transfer-Encoding 8bit
X-Gmane-NNTP-Posting-Host 151.62.69.113
User-Agent Gnus/5.13 (Gnus v5.13) Emacs/24.5.50 (gnu/linux)
Cancel-Lock sha1:ON2px5A0EQWhjyxOB7Adu9pkt78=
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.20+
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.16.1432473331.5151.python-list@python.org> (permalink)
Lines 160
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1432473331 news.xs4all.nl 2958 [2001:888:2000:d::a6]:49599
X-Complaints-To abuse@xs4all.nl
Xref csiph.com comp.lang.python:91178

Show key headers only | View raw


Chris Angelico <rosuav@gmail.com> writes:

> On Sat, May 23, 2015 at 5:12 AM, Lele Gaifax <lele@metapensiero.it> wrote:
>> You are conflating two different layers, core and ORM. ORM relationships can
>> be declared either on the parent or on the child, it's up to your taste.
>
> Not sure why that's distinguishable. If I have two tables like this:
>
> Users:
>     id sequential primary key
>     name text
>
> Tasks
>     id sequential primary key
>     owner integer
>     assignee integer
>
> Both the owner and the assignee refer to the Users table; the owner is
> a mandatory connection (every task was created by someone, who
> initially owns it), and the assignee is an optional connection (a
> newly-created task isn't assigned to anyone). With me so far? Okay.
>
> Now, if I were to represent these tables in SQLAlchemy, obviously I
> need to have foreign key relationships encoded in SQLAlchemy. But if
> I'm to enforce these relationships on the underlying database, it's
> equally obvious that I need foreign key constraints. I would expect
> that a relationship encoded in SQLAlchemy should cause the creation of
> a constraint in the database. They're fundamentally the same thing.

No. A "relationship" is an ORM thingie, and can happily exist without an
underlaying constraint in the database.

> My point about backwards is that my tables here are declared in a
> strict order: parent table, then child table. In the child table, a
> constraint is created by saying "references Users", and the Users
> table already exists. At no point is there ever a forward reference.
> Code would look like this:
>
> create table Users (id serial primary key, name text not null default '');
> create table Tasks (id serial primary key, owner integer not null
> references Users, assignee integer references Users);
>
> But with SQLAlchemy, you have a tag in the Users table's definition
> saying that it has a relationship with Tasks, as well as a foreign key
> in Tasks stating the connection to Users. That violates "Define Before
> Use", which isn't a strict policy, but it does feel a little bit
> "dirty".

As said, that's not how I'd code it, as I'd probably implement those classes
as

class User(Base):
     id = Column(...)
     name = Column(...)

class Task(Base):
     id = Column(...)
     owner_id = Column(...)
     assignee_id = Column(...)

     owned_by = relationship('User', primaryjoin='User.id==Task.owner_id',
                             backref='own_tasks')
     assigned_to = relationship('User', primaryjoin='User.id==Task.assigned_id',
                             backref='assigned_tasks')

>>> When magic works, it's great; but when anything goes wrong, it's harder to
>>> see what happened.
>>
>> The same can be said of almost any upper layer in a software stack.
>
> Precisely. All magic has to justify itself. Some can, easily. Some
> can't. A lot is in the middle, where it's part of the tradeoffs.
>
>>> Also, when does a transaction begin and end?
>>
>> When I need transactions (that is, when I'm changing the database) I'm very
>> picky and use explicit begins, commits and rollbacks, so I don't recall
>> experiencing that doubt.
>
> That's all very well when you write your own code. Now try picking up
> someone else's code. Or, for a mid-way concern, try explaining to a
> junior developer how to make sure his transactions are right. With
> psycopg2, it's easy enough to do this:
>
> with conn, conn.cursor() as cur:
>     cur.execute("....")
>     cur.execute("....")

You're kidding, of course: on SA side you imagine a complex code written by
somebody else, while on the other side a plain sequence of statements. You can
write almost the same code either with SA (which at it's low level has a plain
DBAPI connection):

  http://docs.sqlalchemy.org/en/rel_1_0/core/connections.html#using-transactions

> When the with block exits, the transaction is either committed (if all
> went well) or rolled back (if an exception was raised). It's very
> simple, easy to do, and easy to audit ("all SQL queries must be inside
> a with block that grants a cursor", and possibly "cursor-granting with
> blocks must not be nested").

As you can see, there is almost no difference when using the equivalent SA
idiom.

>
>>> If you session.commit() in the middle of iterating over a query, will it
>>> break the query? What if you roll back? Can you see, instantly, in your
>>> code?
>>
>> Why would you do that? Are you closing your files while you iterate them,
>> without leaving the loop in some way at the same time?
>
> There's advice out there on the internet that says that committing
> periodically in the middle of a big job makes your code run faster.

No, I think you mean "flushing" a session, not committing. And again, that's
usually recommended when using the ORM layer, not at the SQL core we are
talking about here.

> It's from the PHP + MySQL school of thought, where the assumption is
> that finishing is the most important thing, finishing quickly is a
> close second, and guaranteeing correctness isn't even on the radar.
> Now try coping with code that was written under that model.

That's not how I code database-based applications, neither when using plain
DBAPI, nor with SA. I cannot even imagine using such a wierd approach.

> Fortunately, I haven't actually seen anything quite like this in
> SQLAlchemy. The worst I saw was a case where someone was iterating
> over a query and performed another query, which did indeed break the
> fetching of results. But the more magic you have, the less obvious
> that is.

I cannot understand your example: it's not so uncommon the need to perform a
query for each row of a previous one, and it's surely well supported at every
level, in SA.

>> I often have to deal with multiple DB engines at the same time, and being
>> able to "write" my queries with an abstract syntax is very valuable for me.
>
> Hmm, I'm not sure there's all that much that this helps with. Thanks
> to a consistent PEP 249 API, changing database engines is often just a
> matter of changing one import and a connection construction line
> (which you'd have to do anyway, given that the credentials will
> change). What else is there for SQLAlchemy to paper over? The
> differences remain; the common ground is already common.

There are a lot of subtle differences in how SQL is implemented by the various
engines out there. Things like "names quoting", "pagination", "data types",
...

Until you do not need a nice way to write the same thing against different
engines you won't appreciate how nice it is being able to do that :)

ciao, lele.
-- 
nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
lele@metapensiero.it  |                 -- Fortunato Depero, 1929.

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Camelot a good tool for me Cecil Westerhof <Cecil@decebal.nl> - 2015-05-22 09:59 +0200
  Re: Camelot a good tool for me Dan Sommers <dan@tombstonezero.net> - 2015-05-22 12:38 +0000
    Re: Camelot a good tool for me Ben Finney <ben+python@benfinney.id.au> - 2015-05-22 23:02 +1000
    Re: Camelot a good tool for me Cecil Westerhof <Cecil@decebal.nl> - 2015-05-22 15:11 +0200
      Re: Camelot a good tool for me Tim Golden <mail@timgolden.me.uk> - 2015-05-22 14:29 +0100
      Re: Camelot a good tool for me Laura Creighton <lac@openend.se> - 2015-05-22 15:57 +0200
      Re: Camelot a good tool for me Lele Gaifax <lele@metapensiero.it> - 2015-05-22 19:24 +0200
      Re: Camelot a good tool for me Chris Angelico <rosuav@gmail.com> - 2015-05-23 03:37 +1000
      Re: Camelot a good tool for me Laura Creighton <lac@openend.se> - 2015-05-22 19:56 +0200
      Re: Camelot a good tool for me Lele Gaifax <lele@metapensiero.it> - 2015-05-22 21:12 +0200
      Re: Camelot a good tool for me Chris Angelico <rosuav@gmail.com> - 2015-05-23 18:59 +1000
      Re: Camelot a good tool for me Lele Gaifax <lele@metapensiero.it> - 2015-05-24 15:15 +0200
  Re: Camelot a good tool for me Laura Creighton <lac@openend.se> - 2015-05-22 15:03 +0200
    Re: Camelot a good tool for me OT beauty of Tk Christian Gollwitzer <auriocus@gmx.de> - 2015-05-22 21:52 +0200
      Re: Camelot a good tool for me OT beauty of Tk Laura Creighton <lac@openend.se> - 2015-05-22 22:13 +0200
  Re: Camelot a good tool for me Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-05-22 15:24 +0100
  Re: Camelot a good tool for me felix <felix@epepm.cupet.cu> - 2015-05-22 10:50 -0400
  Re: Camelot a good tool for me Tim Chase <python.list@tim.thechases.com> - 2015-05-24 07:05 -0500

csiph-web