diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2dc8ec2..ecdf57c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,10 +7,15 @@ and this project adheres to [Python PEP 440 Versioning](https://www.python.org/d
## [Unreleased]
- Nothing yet...
+## [0.24.1] - 2023-11-23
+## Note - The 0.24.x series is the last to support Python 3.7
+### RDFLib v7.0.0 and some other dependencies already don't support 3.7, so PySHACL will drop it from 0.25+
+### Fixed
+- Shape can have multiple values for `sh:not`. Fixes #217
## [0.24.0] - 2023-11-08
-## Note - This is the last version to support Python 3.7
-### RDFLib v7.0.0 and some other dependencies already don't support 3.7, so PySHACL will drop it after this release.
+## Note - The 0.24.x series is the last to support Python 3.7
+### RDFLib v7.0.0 and some other dependencies already don't support 3.7, so PySHACL will drop it from 0.25+
### Added
- Compatibility with RDFLib v7.0.0 - Closes #197
### Fixed
@@ -1073,7 +1078,8 @@ just leaves the files open. Now it is up to the command-line client to close the
- Initial version, limited functionality
-[Unreleased]: https://github.com/RDFLib/pySHACL/compare/v0.24.0...HEAD
+[Unreleased]: https://github.com/RDFLib/pySHACL/compare/v0.24.1...HEAD
+[0.24.1]: https://github.com/RDFLib/pySHACL/compare/v0.24.0...v0.24.1
[0.24.0]: https://github.com/RDFLib/pySHACL/compare/v0.23.0...v0.24.0
[0.23.0]: https://github.com/RDFLib/pySHACL/compare/v0.22.2...v0.23.0
[0.22.2]: https://github.com/RDFLib/pySHACL/compare/v0.22.1...v0.22.2
diff --git a/CITATION.cff b/CITATION.cff
index 429023c..51068b3 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -8,7 +8,7 @@ authors:
given-names: "Nicholas"
orcid: "http://orcid.org/0000-0002-8742-7730"
title: "pySHACL"
-version: 0.24.0
+version: 0.24.1
doi: 10.5281/zenodo.4750840
license: Apache-2.0
date-released: 2022-01-13
diff --git a/Dockerfile b/Dockerfile
index aca70ea..a6bdcf7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,7 +9,7 @@ WORKDIR /home/pyshacl
RUN addgroup -g 1000 -S pyshacl &&\
adduser --disabled-password --gecos "" --home "$(pwd)" --ingroup "pyshacl" --no-create-home --uid 1000 pyshacl
WORKDIR /app
-LABEL org.opencontainers.image.version="0.24.0"
+LABEL org.opencontainers.image.version="0.24.1"
COPY . .
RUN chown -R pyshacl:pyshacl /home/pyshacl /app && chmod -R 775 /home/pyshacl /app
USER pyshacl
diff --git a/README.md b/README.md
index e957714..529c009 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ usage: pyshacl [-h] [-s [SHACL]] [-e [ONT]] [-i {none,rdfs,owlrl,both}] [-m]
[-ef {auto,turtle,xml,json-ld,nt,n3}] [-V] [-o [OUTPUT]]
DataGraph
-PySHACL 0.24.0 command line tool.
+PySHACL 0.24.1 command line tool.
positional arguments:
DataGraph The file containing the Target Data Graph.
diff --git a/poetry.lock b/poetry.lock
index be49699..068dfd7 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -151,13 +151,13 @@ toml = ["tomli"]
[[package]]
name = "exceptiongroup"
-version = "1.1.3"
+version = "1.2.0"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
- {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
+ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
+ {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
]
[package.extras]
@@ -507,13 +507,13 @@ files = [
[[package]]
name = "platformdirs"
-version = "3.11.0"
+version = "4.0.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = true
python-versions = ">=3.7"
files = [
- {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
- {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
+ {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
+ {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
]
[package.dependencies]
@@ -1031,13 +1031,13 @@ files = [
[[package]]
name = "types-setuptools"
-version = "68.2.0.0"
+version = "68.2.0.1"
description = "Typing stubs for setuptools"
optional = true
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "types-setuptools-68.2.0.0.tar.gz", hash = "sha256:a4216f1e2ef29d089877b3af3ab2acf489eb869ccaf905125c69d2dc3932fd85"},
- {file = "types_setuptools-68.2.0.0-py3-none-any.whl", hash = "sha256:77edcc843e53f8fc83bb1a840684841f3dc804ec94562623bfa2ea70d5a2ba1b"},
+ {file = "types-setuptools-68.2.0.1.tar.gz", hash = "sha256:8f31e8201e7969789e0eb23463b53ebe5f67d92417df4b648a6ea3c357ca4f51"},
+ {file = "types_setuptools-68.2.0.1-py3-none-any.whl", hash = "sha256:e9c649559743e9f98c924bec91eae97f3ba208a70686182c3658fd7e81778d37"},
]
[[package]]
@@ -1176,13 +1176,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)"
[[package]]
name = "wcwidth"
-version = "0.2.9"
+version = "0.2.12"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.9-py2.py3-none-any.whl", hash = "sha256:9a929bd8380f6cd9571a968a9c8f4353ca58d7cd812a4822bba831f8d685b223"},
- {file = "wcwidth-0.2.9.tar.gz", hash = "sha256:a675d1a4a2d24ef67096a04b85b02deeecd8e226f57b5e3a72dbb9ed99d27da8"},
+ {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"},
+ {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"},
]
[[package]]
diff --git a/pyproject.toml b/pyproject.toml
index a9a2e8a..c0b75e1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "pyshacl"
-version = "0.24.0"
+version = "0.24.1"
# Don't forget to change the version number in __init__.py, Dockerfile, and CITATION.cff along with this one
description = "Python SHACL Validator"
license = "Apache-2.0"
diff --git a/pyshacl/__init__.py b/pyshacl/__init__.py
index a91d4a2..ce2f030 100644
--- a/pyshacl/__init__.py
+++ b/pyshacl/__init__.py
@@ -5,7 +5,7 @@
from .validate import Validator, validate
# version compliant with https://www.python.org/dev/peps/pep-0440/
-__version__ = '0.24.0'
+__version__ = '0.24.1'
# Don't forget to change the version number in pyproject.toml, Dockerfile, and CITATION.cff along with this one
__all__ = ['validate', 'Validator', '__version__', 'Shape', 'ShapesGraph']
diff --git a/pyshacl/constraints/core/logical_constraints.py b/pyshacl/constraints/core/logical_constraints.py
index 0df5c6b..a2cb3b1 100644
--- a/pyshacl/constraints/core/logical_constraints.py
+++ b/pyshacl/constraints/core/logical_constraints.py
@@ -45,11 +45,6 @@ def __init__(self, shape):
"NotConstraintComponent must have at least one sh:not predicate.",
"https://www.w3.org/TR/shacl/#NotConstraintComponent",
)
- if len(not_list) > 1:
- raise ConstraintLoadError(
- "NotConstraintComponent must have at most one sh:not predicate.",
- "https://www.w3.org/TR/shacl/#NotConstraintComponent",
- )
self.not_list = not_list
@classmethod
diff --git a/test/issues/test_217.py b/test/issues/test_217.py
new file mode 100644
index 0000000..b9319ef
--- /dev/null
+++ b/test/issues/test_217.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+#
+"""
+https://github.com/RDFLib/pySHACL/issues/217
+"""
+import rdflib
+import pyshacl
+import sys
+
+shapes_data = '''\
+@prefix ex: .
+@prefix sh-ex: .
+@prefix sh: .
+
+sh-ex:ClassC-shape
+ a sh:NodeShape ;
+ sh:not
+ [
+ a sh:NodeShape ;
+ sh:class ex:ClassA ;
+ ] ,
+ [
+ a sh:NodeShape ;
+ sh:class ex:ClassB ;
+ ]
+ ;
+ sh:targetClass ex:ClassC ;
+ .
+'''
+
+data_g_text = '''\
+@prefix ex: .
+@prefix kb: .
+@prefix rdfs: .
+
+kb:Thing-1
+ a
+ ex:ClassA ,
+ ex:ClassB
+ ;
+ rdfs:comment "This individual is consistent per OWL and should validate with SHACL."@en ;
+ .
+
+kb:Thing-2
+ a
+ ex:ClassA ,
+ ex:ClassC
+ ;
+ rdfs:comment "This individual is inconsistent per OWL and should not validate with SHACL."@en ;
+ .
+
+kb:Thing-3
+ a
+ ex:ClassB ,
+ ex:ClassC
+ ;
+ rdfs:comment "This individual is inconsistent per OWL and should not validate with SHACL."@en ;
+ .
+'''
+
+
+def test_217():
+ shape_g = rdflib.Graph().parse(data=shapes_data, format='turtle')
+ data_g = rdflib.Graph().parse(data=data_g_text, format="turtle")
+ conforms, results_graph, results_text = pyshacl.validate(
+ data_g, shacl_graph=shape_g, debug=True, meta_shacl=False,
+ )
+ assert not conforms
+ assert "Node kb:Thing-2 conforms to shape" in results_text and "Node kb:Thing-3 conforms to shape" in results_text
+
+
+if __name__ == "__main__":
+ sys.exit(test_217())