Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 63 additions & 61 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,6 @@ jobs:
# to save the cache. So it must come before the thing we want to use
# the cache.
###
- name: Get pip cache epoch
id: pip-cache-epoch
# ``actions/cache`` never replaces an entry: "if the provided key
# matches an existing cache, a new cache is not created". A corrupt
# entry would therefore break every run that restores it until GitHub
# evicts it. Rotating the key weekly abandons such an entry instead.
run: |
echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"

- name: Get pip cache dir
id: pip-cache
run: |
Expand All @@ -140,19 +131,30 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}-${{ steps.pip-cache-epoch.outputs.week }}

key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}

- name: Install Build Dependencies (3.15)
if: startsWith(matrix.python-version, '3.15')
run: |
python -m pip install -U pip
pip install -U "setuptools >= 78.1.1,< 82" wheel twine cffi pycparser
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
retry python -m pip install -U pip
retry pip install -U "setuptools >= 78.1.1,< 82" wheel twine cffi pycparser
- name: Install Build Dependencies
if: ${{ !startsWith(matrix.python-version, '3.15') }}
run: |
python -m pip install -U pip
pip install -U "setuptools >= 78.1.1,< 82" wheel twine
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
retry python -m pip install -U pip
retry pip install -U "setuptools >= 78.1.1,< 82" wheel twine

- name: Build AccessControl (macOS x86_64)
if: >
Expand Down Expand Up @@ -200,16 +202,28 @@ jobs:
- name: Install AccessControl and dependencies (3.15)
if: startsWith(matrix.python-version, '3.15')
run: |
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
# Install to collect dependencies into the (pip) cache.
# Use "--pre" here because dependencies with support for this future
# Python release may only be available as pre-releases
pip install --pre .[test]
retry pip install --pre .[test]
- name: Install AccessControl and dependencies
if: ${{ !startsWith(matrix.python-version, '3.15') }}
run: |
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
# Install to collect dependencies into the (pip) cache.
python -m pip install -U pip "setuptools >= 78.1.1,< 82"
pip install .[test]
retry python -m pip install -U pip "setuptools >= 78.1.1,< 82"
retry pip install .[test]

- name: Check AccessControl build
run: |
Expand Down Expand Up @@ -290,15 +304,6 @@ jobs:
# to save the cache. So it must come before the thing we want to use
# the cache.
###
- name: Get pip cache epoch
id: pip-cache-epoch
# ``actions/cache`` never replaces an entry: "if the provided key
# matches an existing cache, a new cache is not created". A corrupt
# entry would therefore break every run that restores it until GitHub
# evicts it. Rotating the key weekly abandons such an entry instead.
run: |
echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"

- name: Get pip cache dir
id: pip-cache
run: |
Expand All @@ -308,8 +313,7 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}-${{ steps.pip-cache-epoch.outputs.week }}

key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}
- name: Download AccessControl wheel (Linux/macOS)
if: "!startsWith(runner.os, 'Windows')"
uses: actions/download-artifact@v8
Expand All @@ -326,30 +330,42 @@ jobs:
- name: Install AccessControl ${{ matrix.python-version }}
if: startsWith(matrix.python-version, '3.15')
run: |
pip install -U wheel "setuptools >= 78.1.1,< 82"
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
retry pip install -U wheel "setuptools >= 78.1.1,< 82"
# coverage might have a wheel on PyPI for a future python version which is
# not ABI compatible with the current one, so build it from sdist:
pip install -U --no-binary :all: coverage[toml]
retry pip install -U --no-binary :all: coverage[toml]
# Unzip into src/ so that testrunner can find the .so files
# when we ask it to load tests from that directory. This
# might also save some build time?
ls -l dist/
unzip -n dist/*.whl -d src
# Use "--pre" here because dependencies with support for this future
# Python release may only be available as pre-releases
pip install --pre -e .[test]
retry pip install --pre -e .[test]
- name: Install AccessControl
if: ${{ !startsWith(matrix.python-version, '3.15') }}
run: |
pip install -U wheel "setuptools >= 78.1.1,< 82"
pip install -U coverage[toml]
pip install -U 'cffi; platform_python_implementation == "CPython"'
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
retry pip install -U wheel "setuptools >= 78.1.1,< 82"
retry pip install -U coverage[toml]
retry pip install -U 'cffi; platform_python_implementation == "CPython"'
# Unzip into src/ so that testrunner can find the .so files
# when we ask it to load tests from that directory. This
# might also save some build time?
ls -l dist/
unzip -n dist/*.whl -d src
pip install -e .[test]
retry pip install -e .[test]
- name: Run tests with C extensions
if: ${{ !startsWith(matrix.python-version, 'pypy') }}
run: |
Expand Down Expand Up @@ -404,15 +420,6 @@ jobs:
# to save the cache. So it must come before the thing we want to use
# the cache.
###
- name: Get pip cache epoch
id: pip-cache-epoch
# ``actions/cache`` never replaces an entry: "if the provided key
# matches an existing cache, a new cache is not created". A corrupt
# entry would therefore break every run that restores it until GitHub
# evicts it. Rotating the key weekly abandons such an entry instead.
run: |
echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"

- name: Get pip cache dir
id: pip-cache
run: |
Expand All @@ -422,18 +429,23 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}-${{ steps.pip-cache-epoch.outputs.week }}

key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ matrix.python-version }}
- name: Download AccessControl wheel
uses: actions/download-artifact@v8
with:
name: AccessControl-${{ runner.os }}-${{ matrix.python-version }}.whl
path: dist/
- name: Install AccessControl
run: |
pip install -U wheel
pip install -U tox
pip install -U "`ls dist/*.whl`[docs]"
# PyPI downloads are occasionally cut off mid-transfer, which makes
# pip fail with ``IncompleteRead``. pip does not retry a truncated
# download, so retry the complete command. Purge pip's cache before
# the last attempt: should a truncated download ever get *cached*,
# it would fail every attempt in the same way.
retry() { for i in 1 2; do "$@" && return 0; echo "Attempt $i failed, retrying in 15s ..."; sleep 15; done; pip cache purge || true; "$@"; }
retry pip install -U wheel
retry pip install -U tox
retry pip install -U "`ls dist/*.whl`[docs]"
- name: Run release check
env:
ZOPE_INTERFACE_STRICT_IRO: 1
Expand Down Expand Up @@ -472,15 +484,6 @@ jobs:
# to save the cache. So it must come before the thing we want to use
# the cache.
###
- name: Get pip cache epoch
id: pip-cache-epoch
# ``actions/cache`` never replaces an entry: "if the provided key
# matches an existing cache, a new cache is not created". A corrupt
# entry would therefore break every run that restores it until GitHub
# evicts it. Rotating the key weekly abandons such an entry instead.
run: |
echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"

- name: Get pip cache dir
id: pip-cache
run: |
Expand All @@ -490,8 +493,7 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip_manylinux-${{ matrix.image }}-${{ matrix.python-version }}-${{ steps.pip-cache-epoch.outputs.week }}

key: ${{ runner.os }}-pip_manylinux-${{ matrix.image }}-${{ matrix.python-version }}

- name: Update pip
run: python -m pip install -U pip
Expand Down
2 changes: 1 addition & 1 deletion .meta.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/c-code
[meta]
template = "c-code"
commit-id = "9333ca19"
commit-id = "7cab96bb"

[python]
with-windows = true
Expand Down
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
# https://github.com/zopefoundation/meta/tree/master/src/zope/meta/c-code
minimum_pre_commit_version: '3.6'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/isort
rev: "8.0.1"
hooks:
Expand All @@ -27,3 +36,7 @@ repos:
- id: flake8
additional_dependencies:
- flake8-debugger == 4.1.2
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v1.0.2
hooks:
- id: sphinx-lint
2 changes: 1 addition & 1 deletion COPYRIGHT.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Zope Foundation and Contributors
Zope Foundation and Contributors
28 changes: 14 additions & 14 deletions docs/AccessControl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ Types of access

A "type of access" is a named grouping of 0 or more of the
permissions defined by an object. All objects have one predefined
type of access called Full Access (all permissions defined by that
object). A user who has the special role "Manager" always has Full
Access to all objects at or below the level in the object hierarchy
type of access called Full Access (all permissions defined by that
object). A user who has the special role "Manager" always has Full
Access to all objects at or below the level in the object hierarchy
at which the user is defined.

New types of access may be defined as combinations of the
various permissions defined by a given object. These new
types of access may be defined by the programmer, or by
users at runtime.
users at runtime.



Expand All @@ -50,13 +50,13 @@ A role is a name that ties users (authentication of identity)
to permissions (authorization for that identity) in the system.
Roles may be defined in any Folder (or Folderish) object in the
system. Sub folders can make use of roles defined higher in the
hierarchy. These roles can be assigned to users. All users,
including non-authenticated users have the built-in role of
"Anonymous".
hierarchy. These roles can be assigned to users. All users,
including non-authenticated users have the built-in role of
"Anonymous".

Principia objects allow the association of defined roles
with a single "type of access" each, in the context of that
object. A single role is associated with one and only one
Principia objects allow the association of defined roles
with a single "type of access" each, in the context of that
object. A single role is associated with one and only one
type of access in the context of a given object.


Expand Down Expand Up @@ -191,14 +191,14 @@ Example:
)

The developer may also predefine useful types of access, by
specifying an __ac_types__ attribute. This should be a tuple of
tuples, where each tuple represents a type of access and contains
a string name as its first element and a list of permission names
specifying an __ac_types__ attribute. This should be a tuple of
tuples, where each tuple represents a type of access and contains
a string name as its first element and a list of permission names
as its second element.

By default, only "Full Access" is defined (by the RoleManager mixin).
If you wish to override __ac_types__ to provide convenient types of
access, you must always be sure to define "Full Access" as containing
access, you must always be sure to define "Full Access" as containing
the names of all possible permissions for your object.

Example:
Expand Down
2 changes: 1 addition & 1 deletion src/AccessControl/meta.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
name="permission"
schema="zope.security.zcml.IPermissionDirective"
handler=".security.PermissionDirective"/>

<meta:directive
name="role"
usedIn="zope.security.zcml.IPermissionDirective"
Expand Down
Loading