From: Mike Bayer Date: Sun, 2 Oct 2022 02:24:38 +0000 (-0400) Subject: add disable doctest tag for autodoc test suite X-Git-Tag: rel_2_0_0b1~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2c20d8a532dc302ea324ee00b2f18e58b98d382;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git add disable doctest tag for autodoc test suite ahead of trying to get everything formatted, some more flexibility so that we can use doctest for all python + sql code, while still being able to tell the test suite to not run doctests on a sample. All of the "non-console python with SQL" in the docs is because I was showing an example that I didn't want tested. Change-Id: Iae876ae1ffd93c36b096c6c2d6048843ae9698c8 --- diff --git a/doc/build/tutorial/orm_related_objects.rst b/doc/build/tutorial/orm_related_objects.rst index 4c16b146a0..a23c3369ba 100644 --- a/doc/build/tutorial/orm_related_objects.rst +++ b/doc/build/tutorial/orm_related_objects.rst @@ -615,45 +615,58 @@ One way to use :func:`_orm.raiseload` is to configure it on to the value ``"raise_on_sql"``, so that for a particular mapping, a certain relationship will never try to emit SQL: -.. sourcecode:: python - - from sqlalchemy.orm import Mapped - from sqlalchemy.orm import relationship - +.. setup code - class User(Base): - __tablename__ = "user_account" + >>> class Base(DeclarativeBase): + ... pass - # ... mapped_column() mappings +:: - addresses: Mapped[list["Address"]] = relationship( - back_populates="user", lazy="raise_on_sql" - ) + >>> from sqlalchemy.orm import Mapped + >>> from sqlalchemy.orm import relationship - class Address(Base): - __tablename__ = "address" + >>> class User(Base): + ... __tablename__ = "user_account" + ... id: Mapped[int] = mapped_column(primary_key=True) + ... addresses: Mapped[list["Address"]] = relationship( + ... back_populates="user", lazy="raise_on_sql" + ... ) - # ... mapped_column() mappings - user: Mapped["User"] = relationship(back_populates="addresses", lazy="raise_on_sql") + >>> class Address(Base): + ... __tablename__ = "address" + ... id: Mapped[int] = mapped_column(primary_key=True) + ... user_id: Mapped[int] = mapped_column(ForeignKey("user_account.id")) + ... user: Mapped["User"] = relationship(back_populates="addresses", lazy="raise_on_sql") Using such a mapping, the application is blocked from lazy loading, -indicating that a particular query would need to specify a loader strategy: - -.. sourcecode:: python +indicating that a particular query would need to specify a loader strategy:: - u1 = s.execute(select(User)).scalars().first() - u1.addresses + >>> u1 = session.execute(select(User)).scalars().first() + {opensql}SELECT user_account.id FROM user_account + [...] () + {stop}>>> u1.addresses + Traceback (most recent call last): + ... sqlalchemy.exc.InvalidRequestError: 'User.addresses' is not available due to lazy='raise_on_sql' The exception would indicate that this collection should be loaded up front -instead: +instead:: -.. sourcecode:: python - - u1 = s.execute(select(User).options(selectinload(User.addresses))).scalars().first() + >>> u1 = ( + ... session.execute(select(User).options(selectinload(User.addresses))) + ... .scalars() + ... .first() + ... ) + {opensql}SELECT user_account.id + FROM user_account + [...] () + SELECT address.user_id AS address_user_id, address.id AS address_id + FROM address + WHERE address.user_id IN (?, ?, ?, ?, ?, ?) + [...] (1, 2, 3, 4, 5, 6) The ``lazy="raise_on_sql"`` option tries to be smart about many-to-one relationships as well; above, if the ``Address.user`` attribute of an diff --git a/test/base/test_tutorials.py b/test/base/test_tutorials.py index 31207c7a51..0d0ed2bd93 100644 --- a/test/base/test_tutorials.py +++ b/test/base/test_tutorials.py @@ -81,37 +81,35 @@ class DocTest(fixtures.TestBase): config.skip_test("Can't find documentation file %r" % path) buf = [] - line_counter = 0 - last_line_counter = 0 + with open(path, encoding="utf-8") as file_: def load_include(m): fname = m.group(1) sub_path = os.path.join(os.path.dirname(path), fname) with open(sub_path, encoding="utf-8") as file_: - for line in file_: - buf.append(line) + for i, line in enumerate(file_, 1): + buf.append((i, line)) return fname def run_buf(fname, is_include): if not buf: return - nonlocal last_line_counter + test = parser.get_doctest( - "".join(buf), + "".join(line for _, line in buf), globs, fname, fname, - last_line_counter if not is_include else 0, + buf[0][0], ) buf[:] = [] runner.run(test, clear_globs=False) globs.update(test.globs) - if not is_include: - last_line_counter = line_counter + doctest_enabled = True - for line in file_: + for line_counter, line in enumerate(file_, 1): line = re.sub(r"{(?:stop|sql|opensql)}", "", line) include = re.match(r"\.\. doctest-include (.+\.rst)", line) @@ -119,9 +117,17 @@ class DocTest(fixtures.TestBase): run_buf(fname, False) include_fname = load_include(include) run_buf(include_fname, True) + + doctest_disable = re.match( + r"\.\. doctest-(enable|disable)", line + ) + if doctest_disable: + doctest_enabled = doctest_disable.group(1) == "enable" + + if doctest_enabled: + buf.append((line_counter, line)) else: - buf.append(line) - line_counter += 1 + buf.append((line_counter, "\n")) run_buf(fname, False)