From f5023ceef3858a4ebbef8d401d10f6493e773b75 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 7 Jul 2011 11:34:59 -0400 Subject: [PATCH] - add a latex Makefile to texinputs that gets copied on latex build, ensures pdflatex/latex errors are totally ignored - fix all SQL/code examples in the inherits doc to be within 79 chars. will need to do this for all the docs to get pdf to not look crappy. - add an abspath to the "templates" dir, not sure of the rationale here but is harmless, [ticket:2211] - integrate pdf build with site-mako build --- doc/build/Makefile | 3 + doc/build/conf.py | 4 +- doc/build/orm/inheritance.rst | 141 ++++++++++++++++++++++++---------- doc/build/texinputs/Makefile | 64 +++++++++++++++ 4 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 doc/build/texinputs/Makefile diff --git a/doc/build/Makefile b/doc/build/Makefile index a8d26340f5..2ee70dfb8b 100644 --- a/doc/build/Makefile +++ b/doc/build/Makefile @@ -50,6 +50,8 @@ dist-html: site-mako: $(SPHINXBUILD) -b html -A mako_layout=site $(ALLSPHINXOPTS) $(BUILDDIR)/site + $(MAKE) latexpdf + cp $(BUILDDIR)/latex/*.pdf $(BUILDDIR)/site/ @echo @echo "Build finished. The Mako pages are in $(BUILDDIR)/site." @@ -112,6 +114,7 @@ latex: latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + cp texinputs/* $(BUILDDIR)/latex/ @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." diff --git a/doc/build/conf.py b/doc/build/conf.py index 7982ff97ef..592c548829 100644 --- a/doc/build/conf.py +++ b/doc/build/conf.py @@ -36,7 +36,9 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'builder.builders'] # Add any paths that contain templates here, relative to this directory. -templates_path = ['templates'] +# not sure why abspath() is needed here, some users +# have reported this. +templates_path = [os.path.abspath('templates')] nitpicky = True diff --git a/doc/build/orm/inheritance.rst b/doc/build/orm/inheritance.rst index 1105423564..ee3d36a570 100644 --- a/doc/build/orm/inheritance.rst +++ b/doc/build/orm/inheritance.rst @@ -28,14 +28,20 @@ For the following sections, assume this class relationship: self.name = name self.manager_data = manager_data def __repr__(self): - return self.__class__.__name__ + " " + self.name + " " + self.manager_data + return ( + self.__class__.__name__ + " " + + self.name + " " + self.manager_data + ) class Engineer(Employee): def __init__(self, name, engineer_info): self.name = name self.engineer_info = engineer_info def __repr__(self): - return self.__class__.__name__ + " " + self.name + " " + self.engineer_info + return ( + self.__class__.__name__ + " " + + self.name + " " + self.engineer_info + ) Joined Table Inheritance ------------------------- @@ -74,12 +80,16 @@ parent, and even a custom join condition can be specified between parent and child tables instead of using a foreign key:: engineers = Table('engineers', metadata, - Column('employee_id', Integer, ForeignKey('employees.employee_id'), primary_key=True), + Column('employee_id', Integer, + ForeignKey('employees.employee_id'), + primary_key=True), Column('engineer_info', String(50)), ) managers = Table('managers', metadata, - Column('employee_id', Integer, ForeignKey('employees.employee_id'), primary_key=True), + Column('employee_id', Integer, + ForeignKey('employees.employee_id'), + primary_key=True), Column('manager_data', String(50)), ) @@ -104,9 +114,12 @@ stored in the polymorphic discriminator column. .. sourcecode:: python+sql - mapper(Employee, employees, polymorphic_on=employees.c.type, polymorphic_identity='employee') - mapper(Engineer, engineers, inherits=Employee, polymorphic_identity='engineer') - mapper(Manager, managers, inherits=Employee, polymorphic_identity='manager') + mapper(Employee, employees, polymorphic_on=employees.c.type, + polymorphic_identity='employee') + mapper(Engineer, engineers, inherits=Employee, + polymorphic_identity='engineer') + mapper(Manager, managers, inherits=Employee, + polymorphic_identity='manager') And that's it. Querying against ``Employee`` will return a combination of ``Employee``, ``Engineer`` and ``Manager`` objects. Newly saved ``Engineer``, @@ -132,7 +145,8 @@ SQL such as this: .. sourcecode:: python+sql {opensql} - SELECT employees.employee_id AS employees_employee_id, employees.name AS employees_name, employees.type AS employees_type + SELECT employees.employee_id AS employees_employee_id, + employees.name AS employees_name, employees.type AS employees_type FROM employees [] @@ -145,11 +159,13 @@ issued along the lines of: .. sourcecode:: python+sql {opensql} - SELECT managers.employee_id AS managers_employee_id, managers.manager_data AS managers_manager_data + SELECT managers.employee_id AS managers_employee_id, + managers.manager_data AS managers_manager_data FROM managers WHERE ? = managers.employee_id [5] - SELECT engineers.employee_id AS engineers_employee_id, engineers.engineer_info AS engineers_engineer_info + SELECT engineers.employee_id AS engineers_employee_id, + engineers.engineer_info AS engineers_engineer_info FROM engineers WHERE ? = engineers.employee_id [2] @@ -174,8 +190,18 @@ produces a query which joins the ``employees`` table to both the ``engineers`` a query.all() {opensql} - SELECT employees.employee_id AS employees_employee_id, engineers.employee_id AS engineers_employee_id, managers.employee_id AS managers_employee_id, employees.name AS employees_name, employees.type AS employees_type, engineers.engineer_info AS engineers_engineer_info, managers.manager_data AS managers_manager_data - FROM employees LEFT OUTER JOIN engineers ON employees.employee_id = engineers.employee_id LEFT OUTER JOIN managers ON employees.employee_id = managers.employee_id + SELECT employees.employee_id AS employees_employee_id, + engineers.employee_id AS engineers_employee_id, + managers.employee_id AS managers_employee_id, + employees.name AS employees_name, + employees.type AS employees_type, + engineers.engineer_info AS engineers_engineer_info, + managers.manager_data AS managers_manager_data + FROM employees + LEFT OUTER JOIN engineers + ON employees.employee_id = engineers.employee_id + LEFT OUTER JOIN managers + ON employees.employee_id = managers.employee_id [] :func:`~sqlalchemy.orm.query.Query.with_polymorphic` accepts a single class or @@ -202,7 +228,10 @@ should be used to load polymorphically: .. sourcecode:: python+sql # custom selectable - query.with_polymorphic([Engineer, Manager], employees.outerjoin(managers).outerjoin(engineers)) + query.with_polymorphic( + [Engineer, Manager], + employees.outerjoin(managers).outerjoin(engineers) + ) :func:`~sqlalchemy.orm.query.Query.with_polymorphic` is also needed when you wish to add filter criteria that are specific to one or more @@ -224,10 +253,13 @@ followed by a selectable. .. sourcecode:: python+sql - mapper(Employee, employees, polymorphic_on=employees.c.type, \ - polymorphic_identity='employee', with_polymorphic='*') - mapper(Engineer, engineers, inherits=Employee, polymorphic_identity='engineer') - mapper(Manager, managers, inherits=Employee, polymorphic_identity='manager') + mapper(Employee, employees, polymorphic_on=employees.c.type, + polymorphic_identity='employee', + with_polymorphic='*') + mapper(Engineer, engineers, inherits=Employee, + polymorphic_identity='engineer') + mapper(Manager, managers, inherits=Employee, + polymorphic_identity='manager') The above mapping will produce a query similar to that of ``with_polymorphic('*')`` for every query of ``Employee`` objects. @@ -262,7 +294,8 @@ what's specified in the :meth:`.Session.query`, :meth:`.Query.filter`, or session.query(Manager.manager_data).select_from(manager) - session.query(engineer.c.id).filter(engineer.c.engineer_info==manager.c.manager_data) + session.query(engineer.c.id).\ + filter(engineer.c.engineer_info==manager.c.manager_data) Creating Joins to Specific Subtypes +++++++++++++++++++++++++++++++++++ @@ -304,12 +337,16 @@ against the ``Engineer`` class, we can tell those methods to join or subquery against the joined table representing the subclass using the :func:`~sqlalchemy.orm.interfaces.PropComparator.of_type` operator:: - session.query(Company).join(Company.employees.of_type(Engineer)).filter(Engineer.engineer_info=='someinfo') + session.query(Company).\ + join(Company.employees.of_type(Engineer)).\ + filter(Engineer.engineer_info=='someinfo') A longhand version of this would involve spelling out the full target selectable within a 2-tuple:: - session.query(Company).join((employees.join(engineers), Company.employees)).filter(Engineer.engineer_info=='someinfo') + session.query(Company).\ + join((employees.join(engineers), Company.employees)).\ + filter(Engineer.engineer_info=='someinfo') Currently, :func:`~sqlalchemy.orm.interfaces.PropComparator.of_type` accepts a single class argument. It may be expanded later on to accept multiple classes. @@ -318,8 +355,15 @@ flexibility: .. sourcecode:: python+sql - session.query(Company).join((employees.outerjoin(engineers).outerjoin(managers), Company.employees)).\ - filter(or_(Engineer.engineer_info=='someinfo', Manager.manager_data=='somedata')) + session.query(Company).\ + join( + (employees.outerjoin(engineers).outerjoin(managers), + Company.employees) + ).\ + filter( + or_(Engineer.engineer_info=='someinfo', + Manager.manager_data=='somedata') + ) The ``any()`` and ``has()`` operators also can be used with :func:`~sqlalchemy.orm.interfaces.PropComparator.of_type` when the embedded @@ -327,7 +371,11 @@ criterion is in terms of a subclass: .. sourcecode:: python+sql - session.query(Company).filter(Company.employees.of_type(Engineer).any(Engineer.engineer_info=='someinfo')).all() + session.query(Company).\ + filter( + Company.employees.of_type(Engineer). + any(Engineer.engineer_info=='someinfo') + ).all() Note that the ``any()`` and ``has()`` are both shorthand for a correlated EXISTS query. To build one by hand looks like: @@ -336,7 +384,8 @@ EXISTS query. To build one by hand looks like: session.query(Company).filter( exists([1], - and_(Engineer.engineer_info=='someinfo', employees.c.company_id==companies.c.company_id), + and_(Engineer.engineer_info=='someinfo', + employees.c.company_id==companies.c.company_id), from_obj=employees.join(engineers) ) ).all() @@ -369,8 +418,10 @@ for the inheriting classes, leave their ``table`` parameter blank: employee_mapper = mapper(Employee, employees_table, \ polymorphic_on=employees_table.c.type, polymorphic_identity='employee') - manager_mapper = mapper(Manager, inherits=employee_mapper, polymorphic_identity='manager') - engineer_mapper = mapper(Engineer, inherits=employee_mapper, polymorphic_identity='engineer') + manager_mapper = mapper(Manager, inherits=employee_mapper, + polymorphic_identity='manager') + engineer_mapper = mapper(Engineer, inherits=employee_mapper, + polymorphic_identity='engineer') Note that the mappers for the derived classes Manager and Engineer omit the specification of their associated table, as it is inherited from the @@ -429,12 +480,18 @@ each subselect: 'engineer': engineers_table }, 'type', 'pjoin') - employee_mapper = mapper(Employee, employees_table, with_polymorphic=('*', pjoin), \ - polymorphic_on=pjoin.c.type, polymorphic_identity='employee') - manager_mapper = mapper(Manager, managers_table, inherits=employee_mapper, \ - concrete=True, polymorphic_identity='manager') - engineer_mapper = mapper(Engineer, engineers_table, inherits=employee_mapper, \ - concrete=True, polymorphic_identity='engineer') + employee_mapper = mapper(Employee, employees_table, + with_polymorphic=('*', pjoin), + polymorphic_on=pjoin.c.type, + polymorphic_identity='employee') + manager_mapper = mapper(Manager, managers_table, + inherits=employee_mapper, + concrete=True, + polymorphic_identity='manager') + engineer_mapper = mapper(Engineer, engineers_table, + inherits=employee_mapper, + concrete=True, + polymorphic_identity='engineer') Upon select, the polymorphic union produces a query like this: @@ -442,18 +499,23 @@ Upon select, the polymorphic union produces a query like this: session.query(Employee).all() {opensql} - SELECT pjoin.type AS pjoin_type, pjoin.manager_data AS pjoin_manager_data, pjoin.employee_id AS pjoin_employee_id, + SELECT pjoin.type AS pjoin_type, + pjoin.manager_data AS pjoin_manager_data, + pjoin.employee_id AS pjoin_employee_id, pjoin.name AS pjoin_name, pjoin.engineer_info AS pjoin_engineer_info FROM ( - SELECT employees.employee_id AS employee_id, CAST(NULL AS VARCHAR(50)) AS manager_data, employees.name AS name, - CAST(NULL AS VARCHAR(50)) AS engineer_info, 'employee' AS type + SELECT employees.employee_id AS employee_id, + CAST(NULL AS VARCHAR(50)) AS manager_data, employees.name AS name, + CAST(NULL AS VARCHAR(50)) AS engineer_info, 'employee' AS type FROM employees UNION ALL - SELECT managers.employee_id AS employee_id, managers.manager_data AS manager_data, managers.name AS name, - CAST(NULL AS VARCHAR(50)) AS engineer_info, 'manager' AS type + SELECT managers.employee_id AS employee_id, + managers.manager_data AS manager_data, managers.name AS name, + CAST(NULL AS VARCHAR(50)) AS engineer_info, 'manager' AS type FROM managers UNION ALL - SELECT engineers.employee_id AS employee_id, CAST(NULL AS VARCHAR(50)) AS manager_data, engineers.name AS name, + SELECT engineers.employee_id AS employee_id, + CAST(NULL AS VARCHAR(50)) AS manager_data, engineers.name AS name, engineers.engineer_info AS engineer_info, 'engineer' AS type FROM engineers ) AS pjoin @@ -573,7 +635,8 @@ bidirectionally reference ``C``:: 'some_c':relationship(C, back_populates='many_a') }) mapper(C, c_table, properties={ - 'many_a':relationship(A, collection_class=set, back_populates='some_c'), + 'many_a':relationship(A, collection_class=set, + back_populates='some_c'), }) Using Inheritance with Declarative diff --git a/doc/build/texinputs/Makefile b/doc/build/texinputs/Makefile new file mode 100644 index 0000000000..50da172e47 --- /dev/null +++ b/doc/build/texinputs/Makefile @@ -0,0 +1,64 @@ +# Makefile for Sphinx LaTeX output + +ALLDOCS = $(basename $(wildcard *.tex)) +ALLPDF = $(addsuffix .pdf,$(ALLDOCS)) +ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) + +# Prefix for archive names +ARCHIVEPRREFIX = +# Additional LaTeX options +LATEXOPTS = -interaction=nonstopmode + +all: $(ALLPDF) +all-pdf: $(ALLPDF) +all-dvi: $(ALLDVI) +all-ps: all-dvi + for f in *.dvi; do dvips $$f; done +all-pdf-ja: $(wildcard *.tex) + ebb $(wildcard *.pdf *.png *.gif *.jpeg) + platex -kanji=utf8 $(LATEXOPTS) '$<' + platex -kanji=utf8 $(LATEXOPTS) '$<' + platex -kanji=utf8 $(LATEXOPTS) '$<' + -mendex -U -f -d '$(basename $<).dic' -s python.ist '$(basename $<).idx' + platex -kanji=utf8 $(LATEXOPTS) '$<' + platex -kanji=utf8 $(LATEXOPTS) '$<' + dvipdfmx '$(basename $<).dvi' + +zip: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +tar: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +bz2: tar + bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +# The number of LaTeX runs is quite conservative, but I don't expect it +# to get run often, so the little extra time won't hurt. +%.dvi: %.tex + -latex $(LATEXOPTS) '$<' + -latex $(LATEXOPTS) '$<' + -latex $(LATEXOPTS) '$<' + -makeindex -s python.ist '$(basename $<).idx' + -latex $(LATEXOPTS) '$<' + -latex $(LATEXOPTS) '$<' + +%.pdf: %.tex + -pdflatex $(LATEXOPTS) '$<' + -pdflatex $(LATEXOPTS) '$<' + -pdflatex $(LATEXOPTS) '$<' + -makeindex -s python.ist '$(basename $<).idx' + -pdflatex $(LATEXOPTS) '$<' + -pdflatex $(LATEXOPTS) '$<' + +clean: + rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla + +.PHONY: all all-pdf all-dvi all-ps clean + -- 2.39.5