Metadata-Version: 2.4
Name: experimental.noacquisition
Version: 1.1.0b0
Summary: No acquistion during publish traverse
Home-page: http://pypi.org/pypi/collective/experimental.noacquisition
Author: Mauro Amico
Author-email: mauro.amico@gmail.com
License: BSD
Keywords: monkeypatch traverse
Classifier: Framework :: Zope2
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 4.3
Classifier: Framework :: Plone :: 5.0
Classifier: Framework :: Plone :: 5.1
Classifier: Framework :: Plone :: 5.2
Classifier: Framework :: Plone :: 6.0
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Dist: setuptools
Requires-Dist: collective.monkeypatcher
Requires-Dist: Zope2>=2.13.4
Provides-Extra: test
Requires-Dist: Products.CMFPlone[test]; extra == "test"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: summary

.. This README is meant for consumption by humans and pypi. Pypi can render rst files so please do not use Sphinx features.
   If you want to learn more about writing documentation, please check out: http://docs.plone.org/about/documentation_styleguide.html
   This text does not appear on pypi or github. It is a comment.

.. image:: https://img.shields.io/pypi/v/experimental.noacquisition.svg
    :target: https://pypi.org/project/experimental.noacquisition/
    :alt: Latest Version

.. image:: https://img.shields.io/pypi/pyversions/experimental.noacquisition.svg?style=plastic
    :target: https://pypi.org/project/experimental.noacquisition/
    :alt: Supported - Python Versions

.. image:: https://img.shields.io/pypi/dm/experimental.noacquisition.svg
    :target: https://pypi.org/project/experimental.noacquisition/
    :alt: Number of PyPI downloads

.. image:: https://img.shields.io/pypi/l/experimental.noacquisition.svg
    :target: https://pypi.org/project/experimental.noacquisition/
    :alt: License

.. image:: https://github.com/collective/experimental.noacquisition/actions/workflows/tests.yml/badge.svg
    :target: https://github.com/collective/experimental.noacquisition/actions
    :alt: Tests

.. image:: https://coveralls.io/repos/github/collective/experimental.noacquisition/badge.svg?branch=master
    :target: https://coveralls.io/github/collective/experimental.noacquisition?branch=master
    :alt: Coverage



Introduction
============

The problem with “acquisition” and publishTraverse is that the current method returns too many different URLs for the same content. 
For instance here is some potential url for the “kb” page of the plone.org website

- https://plone.org/documentation/kb
- https://plone.org/documentation/manual/kb
- https://plone.org/documentation/kb/manual/kb
- https://plone.org/documentation/manual/spinner.gif/kb
- ...

and here is a generic "Plone" site with two content items "a" and "b" (folderish or not)

- http://example.com/Plone/a
- http://example.com/Plone/a/b/a
- http://example.com/Plone/a
- http://example.com/Plone/b/a
- ...

All the urls above returns 200 with the same content, 
while I would like the "canonical url" to return 200 and the other to return 404.

The behaviour described above constitute a problem because:

* multiple url for the same content is a problem for SEO and is confusing to people. 
  For SEO, in the latest versions Plone introduced the canonical META,
  but IMHO it's just a workaround. 
  People are confused. 
  For example: sometimes some of my editors ask me: 
  "I can't remove the http://example.com/Plone/a/b/a/page. Can you do it for me?"

* the page doesn’t seem really the same on all urls: 
  if you open
  https://plone.org/documentation/kb and
  https://plone.org/documentation/manual/kb the second has a portlet that the first is missing

* removing page from external cache (varnish or squid), for example after a
  content modification, will be a pain. 
  This is because for the same content there could be multiple urls without any control or rules 
  (``collective.purgebyid`` solves this)

* when using subsite (or multiple plone site on the same zope app) the problem is even more annoying: 
  suppose that "a" is a subsite (marked with INavigationRoot) for http://a.example.org and "b" for http://b.example.org.
  Opening the url http://a.example.org/b will probably show the homepage of site "a" inside the "b" site.
  ``collective.siteisolation`` and probably ``collective.lineage`` do something to isolate subsite, 
  but IMHO again are only workarounds.

Versions
========

============ =================== ==============================================
Series       Plone               Implementation
============ =================== ==============================================
``2.x``      6.0, 6.1, 6.2       ``Products.CMFCore.explicitacquisition``
``1.x``      5.2, 6.0, 6.1, 6.2  monkey patch (**this branch**)
============ =================== ==============================================

This is the ``1.x`` series, maintained for Plone 5.2, 6.0, 6.1 and 6.2 (Zope
< 6.2). Since ``Products.CMFCore`` 3.1 (i.e. Plone 6) Plone also ships a
native implementation of this same idea, based on the ``IPubAfterTraversal``
event instead of a monkey patch, and the ``2.x`` series of this package
builds on that instead. That implementation only inspects the *last*
traversed object, so it misses acquired content reached **through** a view
that consumes further path segments -- for instance::

    /folder/acquired_image/@@images/image          served by 2.x, 404 with 1.x
    /folder/acquired_doc/@types/Document           served by 2.x, 404 with 1.x

The monkey patch used here does not have that gap, because it checks at
*every* traversal step. So ``1.x`` gives more complete coverage than
``2.x`` on every Plone version both support.

Usage
=====

This is a monkey patch for publishTraverse method of Zope2's
``ZPublisher.BaseRequest.DefaultPublishTraverse`` and a monkey patch
for ``Products.Archetypes.BaseObject.BaseObject.__bobo_traverse__``

By default invalid traverse is only logged as warning.

For enable raising exceptions, you need to manually modify ``config.py`` changing ``DRYRUN`` to ``False``. 

Or using ``plone.recipe.zope2instance >= 4.2.14``, e.g.::

    [instance]
    recipe = plone.recipe.zope2instance
    eggs =
        experimental.noacquisition
    ...
    initialization =
       from experimental.noacquisition import config
       config.DRYRUN = False


Warning
=======

**USE AT YOUR OWN RISK**

Don't use it, if you don't know exactly what are you doing... at least use leaving ``DRYRUN = True``.


Other solutions
===============

The ``Products.CMFPlone`` branch that used to be linked here, based on the
IPubAfterTraversal event instead of a monkey patch, was merged into
``Products.CMFCore`` itself (3.1+) as
``Products.CMFCore.explicitacquisition``, and is what the ``2.x`` series of
this package builds on. It still doesn't work for all cases, at least when
there is a custom traversal at the end of the request (take a look at the
tests inside this package) -- see `Versions`_ above.

There is also other packages with the same event based approach:
`collective.explicitacquisition <https://github.com/collective/collective.explicitacquisition>`_ and
`collective.redirectacquired <https://github.com/collective/collective.redirectacquired>`_

Changelog
=========

1.1.0b0 (2026-08-12)
--------------------

- Support Plone 6.2 (Zope 6.1): raise the paranoid version check from
  ``Zope < 6`` to ``Zope < 6.2`` (verified that
  ``DefaultPublishTraverse.publishTraverse`` is unchanged between Zope 5.13
  and 6.1), and delegate the final publishability check to
  ``request.ensure_publishable()`` when available (Zope >= 5.10), falling
  back to the old docstring/typeCheck logic on older Zope (e.g. Plone 5.2's
  Zope 4.x). ``ensure_publishable`` also understands the newer
  ``@zpublish`` marker, which the previous docstring-only check did not.
  [mamico]

- CI: pin ``zc.buildout = 3.1.0`` for Plone 5.2 (``test-5.2.x.cfg``).
  Plone 5.2's own pin, 3.0.1, has a race-condition bug in
  ``_move_to_eggs_dir_and_compile()`` that raises a bare
  ``AssertionError`` instead of the real error (fixed in 3.1.0, see
  `buildout/buildout#307 <https://github.com/buildout/buildout/issues/307>`_).
  Stayed below 4.0, which requires Python >= 3.9 and would break
  py27/py36/py37/py38.
  [mamico]

- CI: add Plone 6.1 and 6.2 to the test matrix (py310-py313), bootstrapping
  each from its own official ``https://dist.plone.org/release/<x>/requirements.txt``.
  Comment out ``py27-plone52``, ``py37-plone52`` and ``py38-plone60`` (all
  still work with tox locally): ``actions/setup-python`` can no longer
  install Python 2.7/3.7 on the ubuntu-24.04 runner image, and Plone 6.0's
  current constraints pin ``plone.recipe.zope2instance >= 8.0.0``, which
  requires Python >= 3.9. Also set ``fail-fast: false`` so one broken leg
  stops hiding the others.
  [mamico]

- Replace the Bandit security check (broken: its Docker image is based on
  an archived Debian Buster) with ``ruff --select S``, the equivalent
  ruleset. Renamed ``bandit.yml`` to ``sast.yaml``.
  [mamico]


1.0.0b10 (2023-02-09)
---------------------

- Zope < 6 (no changes)
  [daniele-andreotti]

1.0.0b9 (2020-07-02)
--------------------

- Zope < 5 (no changes)
  [mamico]

1.0.0b7 (2019-12-10)
--------------------

- Zope < 4.2 (no changes)
  [mamico]


1.0.0b6 (2019-11-07)
--------------------

- Python3 Plone 5.2
  [mamico]


1.0.0b5 (2019-06-05)
--------------------

- Zope2 2.13.28 (no changes)
  [mamico]


1.0.0b4 (2018-05-14)
--------------------

- Zope2 2.13.27 (no changes)
  [mamico]


1.0.0b3 (2017-05-09)
--------------------

- Zope2 2.13.26 (no changes)
  [mamico]

1.0.0b2 (2016-06-10)
--------------------

- Zope2 2.13.24
  [mamico]

1.0.0b1 (2015-10-23)
--------------------

- Zope2 2.13.23 (Plone 4.3.7/5.0)
  [mamico]

1.0.0a5 (2014-10-31)
--------------------

- Nothing changed yet.


1.0.0a4 (2014-10-31)
--------------------

- Initial release
