Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into fix-setBody-tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
ale-rt committed Oct 3, 2018
2 parents 0189027 + 7d23b43 commit c095e70
Show file tree
Hide file tree
Showing 16 changed files with 436 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -25,3 +25,5 @@
/var/
coverage.xml
pip-selfcheck.json
Pipfile
Pipfile.lock
12 changes: 8 additions & 4 deletions CHANGES.rst
Expand Up @@ -26,6 +26,10 @@ New features
Bugfixes
++++++++

- Restore controls for reordering items in an Ordered Folder and list them
according to the internal order by default in ZMI.
(`#344 <https://github.com/zopefoundation/Zope/pull/344>`_)

- Call exception view before triggering _unauthorized.
(`#304 <https://github.com/zopefoundation/Zope/pull/304>`_)

Expand Down Expand Up @@ -236,14 +240,14 @@ Breaking changes
- Stop setting ``CLIENT_HOME`` as a builtin, get it via
``App.config.getConfiguration().clienthome`` instead.

- Drop `OFS.History` functionality.
- Drop ``OFS.History`` functionality.

- Removed `OFS.DefaultObservable` - an early predecessor of `zope.event`.
- Removed ``OFS.DefaultObservable`` - an early predecessor of `zope.event`.

- Removed `OFS.ZDOM`. `OFS.SimpleItem.Item` now implements `getParentNode()`.
- Removed ``OFS.ZDOM``. `OFS.SimpleItem.Item` now implements `getParentNode()`.

- Removed special code to create user folders and page templates while creating
new `OFS.Folder` instances.
new ``OFS.Folder` instances.
- Removed the `App.version_txt.getZopeVersion` API, you can use
``pkg_resources.get_distribution('Zope').version`` instead.
Expand Down
1 change: 1 addition & 0 deletions README.rst
Expand Up @@ -40,6 +40,7 @@ Zope can either be installed using:

* `zc.buildout`, see https://zope.readthedocs.io/en/latest/INSTALL-buildout.html
* `virtualenv` and `pip`, see https://zope.readthedocs.io/en/latest/INSTALL-virtualenv.html
* `pipenv`, see https://zope.readthedocs.io/en/latest/INSTALL-pipenv.html

License
=======
Expand Down
1 change: 1 addition & 0 deletions constraints.txt
@@ -0,0 +1 @@
ZServer==4.0b1 ; python_version < '3.0'
81 changes: 81 additions & 0 deletions docs/INSTALL-pipenv.txt
@@ -0,0 +1,81 @@
Installing Zope via ``pipenv``
==============================

.. highlight:: bash

This document describes how to install Zope via ``pipenv``. Python 3 only.

Please note, that the support for Pipenv is considered experimental.

Also, currently there is no support to update the Zope installation via ``pipenv``.


Create a Virtual Environment
----------------------------

.. code-block:: sh

$ python3.6 -m venv zope
$ cd zope


Install pipenv
--------------

.. code-block:: sh

$ bin/pip install pipenv


Install the Zope Software Packages
----------------------------------

Look for the release you want to install on
https://zopefoundation.github.io/Zope/. Than use the specific
version of ``requirements-full.txt`` in the URL, replacing 4.0b4 in the example below.
(Remove the --pre option for final releases.)

.. code-block:: sh

$ bin/pipenv install -r https://zopefoundation.github.io/Zope/releases/4.0b4/requirements-full.txt --pre
...
Successfully installed ...


Creating a Zope instance
------------------------

Once you've installed Zope, you will need to create an "instance
home". This is a directory that contains configuration and data for a
Zope server process. The instance home is created using the
``mkwsgiinstance`` script:

.. code-block:: sh

$ bin/pipenv run mkwsgiinstance -d .

You will be asked to provide a user name and password for an
administrator's account during ``mkwsgiinstance``. To see the available
command-line options, run the script with the ``--help`` option:

.. code-block:: sh

$ bin/pipenv run mkwsgiinstance --help

The `-d .` specifies the directory to create the instance home in.
If you follow the example and choose the current directory, you'll
find the instances files in the subdirectories of the ``virtualenv``:

- ``etc/`` will hold the configuration files.
- ``var/`` will hold the database files.


Starting your created instance
------------------------------

To start your newly created instance, run the provided runwsgi script
with the generated configuration:

.. code-block:: sh

$ bin/pipenv run runwsgi etc/zope.ini
16 changes: 12 additions & 4 deletions docs/INSTALL-virtualenv.rst
Expand Up @@ -40,16 +40,25 @@ Install the Zope Software Packages

Look for the release you want to install on
https://zopefoundation.github.io/Zope/. Than use the specific
version of ``requirements-full.txt`` in the URL, replacing 4.0b4 in the example below:
version of ``requirements-full.txt`` in the URL, replacing 4.0b6 in the example below:

.. code-block:: sh
$ bin/pip install \
-r https://zopefoundation.github.io/Zope/releases/4.0b4/requirements-full.txt
-r https://zopefoundation.github.io/Zope/releases/4.0b6/requirements-full.txt
Obtaining Zope
...
Successfully installed ...
If you are on Python 2 and want to use ZServer instead of WSGI , you'll have to
install that package seperately using the version spec in constraints.txt

.. code-block:: sh
$ bin/pip install \
-c https://zopefoundation.github.io/Zope/releases/4.0b6/constraints.txt \
ZServer
Creating a Zope instance
------------------------
Expand All @@ -58,8 +67,7 @@ Creating a Zope instance

The following steps describe how to install a WSGI based Zope instance.
If you want/have to use ZServer instead of WSGI (Python 2 only!) follow
the documentation `Creating a Zope instance for Zope 2.13`_, as it has not
changed since that version.
the documentation `Creating a Zope instance for Zope 2.13`_.

.. _`Creating a Zope instance for Zope 2.13` : http://zope.readthedocs.io/en/2.13/INSTALL-virtualenv.html#creating-a-zope-instance
Expand Down
4 changes: 4 additions & 0 deletions docs/operation.rst
Expand Up @@ -30,6 +30,10 @@ The section in the configuration file looks like this::
After making any changes to the configuration file, you need to restart any
running Zope server for the affected instance before changes are in effect.

For a full description of the supported sections and directives for
``wsgi.conf``, refer to the machine readable schema description file
``https://rawgit.com/zopefoundation/Zope/master/src/Zope2/Startup/wsgischema.xml``.


Running Zope
------------
Expand Down
1 change: 0 additions & 1 deletion requirements-full.txt
Expand Up @@ -22,7 +22,6 @@ WebTest==2.0.29
ZConfig==3.2.0
ZEO==5.2.0
ZODB==5.4.0
ZServer==4.0b1 ; python_version < '3.0'
Zope2==4.0b1
five.globalrequest==99.1
five.localsitemanager==3.1
Expand Down
48 changes: 48 additions & 0 deletions src/OFS/ObjectManager.py
Expand Up @@ -48,6 +48,7 @@
from zope.interface.interfaces import ComponentLookupError
from zope.lifecycleevent import ObjectAddedEvent
from zope.lifecycleevent import ObjectRemovedEvent
import zope.sequencesort

from App.Common import is_acquired
from App.config import getConfiguration
Expand Down Expand Up @@ -865,6 +866,53 @@ def last_modified(self, ob):
except (DateTimeError, AttributeError):
return ''

security.declareProtected(view_management_screens,
'manage_get_sortedObjects')
def manage_get_sortedObjects(self, sortkey, revkey):
'''
Return dictionaries used for the management page, sorted by sortkey
(which is 'id' or an attribute of the objects). The direction is
determined by rkey, which can be 'asc' for ascending or 'desc' for
descending.
It returns a list of dictionaries, with keys 'id' and 'obj', where 'id'
is the ID of the object as known by the parent and 'obj' is the child
object.
'''
if sortkey not in ['position', 'title', 'meta_type', 'get_size',
'_p_mtime']:
sortkey = 'id'

items = []
for id, obj in self.objectItems():
item = {'id': id, 'obj': obj}
if sortkey not in ['id', 'position'] and hasattr(obj, sortkey):
# add the attribute by which we need to sort
item[sortkey] = getattr(obj, sortkey)
items.append(item)

if sortkey == 'position':
# native ordering of Ordered Folders
if revkey == 'desc':
return list(reversed(items))
else:
return items

if sortkey in ['id', 'title', 'meta_type']:
sort_func = 'strcoll'
else:
sort_func = 'cmp'

sorted_items = zope.sequencesort.sort(
items,
((sortkey, sort_func, revkey), ),
mapping=1
)

# remove the additional attribute
return [
{'id': item['id'], 'obj': item['obj']}
for item in sorted_items
]

# Don't InitializeClass, there is a specific __class_init__ on ObjectManager
# InitializeClass(ObjectManager)
Expand Down
67 changes: 67 additions & 0 deletions src/OFS/tests/testSorting.py
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
import codecs
import Testing.ZopeTestCase
import Testing.testbrowser
import Zope2.App


class SortingTests(Testing.ZopeTestCase.FunctionalTestCase):
"""Browser testing ..Image.File"""

def setUp(self):
super(SortingTests, self).setUp()

Zope2.App.zcml.load_site(force=True)

uf = self.app.acl_users
uf.userFolderAddUser('manager', 'manager_pass', ['Manager'], [])

self.app.manage_addFolder('sortingTest')
self.app.manage_addOrderedFolder('sortingTestOrdered')
for folder in [self.app.sortingTest, self.app.sortingTestOrdered]:
folder.manage_addFile('File2')
folder.manage_addFile('File1')
folder.File1.update_data(u'hällo'.encode('utf-8'))

self.browser = Testing.testbrowser.Browser()
self.browser.addHeader(
'Authorization',
'basic {}'.format(codecs.encode(
b'manager:manager_pass', 'base64').decode()))

def check_order(self, expect_1_before_2):
found_1_before_2 = (
self.browser.contents.find('File2') >
self.browser.contents.find('File1')
)
self.assertEqual(found_1_before_2, expect_1_before_2)

def test_sortby(self):
base_url = 'http://localhost/sortingTest/manage_main?skey=%s&rkey=%s'

self.browser.open(base_url % ('id', 'asc'))
self.check_order(expect_1_before_2=True)

self.browser.open(base_url % ('id', 'desc'))
self.check_order(expect_1_before_2=False)

self.browser.open(base_url % ('get_size', 'asc'))
self.check_order(expect_1_before_2=False)

self.browser.open(base_url % ('get_size', 'desc'))
self.check_order(expect_1_before_2=True)

def test_sortby_ordered(self):
base_url = 'http://localhost/sortingTestOrdered/manage_main?'

self.browser.open(base_url)
self.check_order(expect_1_before_2=False)

self.browser.open(base_url + 'rkey=desc')
self.check_order(expect_1_before_2=True)

self.browser.open(base_url + 'skey=id&rkey=asc')
self.check_order(expect_1_before_2=True)

self.browser.open(base_url + 'skey=id&rkey=desc')
self.check_order(expect_1_before_2=False)

0 comments on commit c095e70

Please sign in to comment.