openSUSE Commits
Threads by month
- ----- 2025 -----
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
January 2024
- 1 participants
- 1743 discussions
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-yattag for openSUSE:Factory checked in at 2024-01-03 12:24:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-yattag (Old)
and /work/SRC/openSUSE:Factory/.python-yattag.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-yattag"
Wed Jan 3 12:24:09 2024 rev:2 rq:1135622 version:1.15.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-yattag/python-yattag.changes 2023-05-04 17:10:41.944408708 +0200
+++ /work/SRC/openSUSE:Factory/.python-yattag.new.28375/python-yattag.changes 2024-01-03 12:24:14.073825533 +0100
@@ -1,0 +2,6 @@
+Fri Dec 29 09:55:11 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 1.15.2:
+ * Add exports to _all__
+
+-------------------------------------------------------------------
Old:
----
yattag-1.15.1.tar.gz
New:
----
yattag-1.15.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-yattag.spec ++++++
--- /var/tmp/diff_new_pack.Rbac3c/_old 2024-01-03 12:24:15.173865726 +0100
+++ /var/tmp/diff_new_pack.Rbac3c/_new 2024-01-03 12:24:15.173865726 +0100
@@ -18,7 +18,7 @@
%define skip_python2 1
Name: python-yattag
-Version: 1.15.1
+Version: 1.15.2
Release: 0
Summary: Generate HTML or XML in a pythonic way
License: LGPL-2.1-only
++++++ yattag-1.15.1.tar.gz -> yattag-1.15.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yattag-1.15.1/PKG-INFO new/yattag-1.15.2/PKG-INFO
--- old/yattag-1.15.1/PKG-INFO 2023-03-03 10:12:12.430634700 +0100
+++ new/yattag-1.15.2/PKG-INFO 2023-10-27 14:17:11.504937400 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: yattag
-Version: 1.15.1
+Version: 1.15.2
Summary: Generate HTML or XML in a pythonic way. Pure python alternative to web template engines.Can fill HTML forms with default values and error messages.
Home-page: https://www.yattag.org
Author: Benjamin Le Forestier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yattag-1.15.1/setup.py new/yattag-1.15.2/setup.py
--- old/yattag-1.15.1/setup.py 2023-03-03 10:08:00.000000000 +0100
+++ new/yattag-1.15.2/setup.py 2023-10-27 14:13:29.000000000 +0200
@@ -5,7 +5,7 @@
setup(
name='yattag',
- version='1.15.1',
+ version='1.15.2',
package_data={"yattag": ["py.typed"]},
packages=['yattag'],
install_requires=[
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yattag-1.15.1/yattag/__init__.py new/yattag-1.15.2/yattag/__init__.py
--- old/yattag-1.15.1/yattag/__init__.py 2023-03-03 10:07:48.000000000 +0100
+++ new/yattag-1.15.2/yattag/__init__.py 2023-10-27 14:13:47.000000000 +0200
@@ -55,7 +55,15 @@
"""
__author__ = "Benjamin Le Forestier (benjamin(a)leforestier.org)"
-__version__ = '1.15.1'
+__version__ = '1.15.2'
+__all__ = [
+ 'Doc',
+ 'SimpleDoc',
+ 'indent',
+ 'NO',
+ 'FIRST_LINE',
+ 'EACH_LINE'
+]
from yattag.simpledoc import SimpleDoc
from yattag.doc import Doc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yattag-1.15.1/yattag.egg-info/PKG-INFO new/yattag-1.15.2/yattag.egg-info/PKG-INFO
--- old/yattag-1.15.1/yattag.egg-info/PKG-INFO 2023-03-03 10:12:12.000000000 +0100
+++ new/yattag-1.15.2/yattag.egg-info/PKG-INFO 2023-10-27 14:17:11.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: yattag
-Version: 1.15.1
+Version: 1.15.2
Summary: Generate HTML or XML in a pythonic way. Pure python alternative to web template engines.Can fill HTML forms with default values and error messages.
Home-page: https://www.yattag.org
Author: Benjamin Le Forestier
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-rpyc for openSUSE:Factory checked in at 2024-01-03 12:24:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-rpyc (Old)
and /work/SRC/openSUSE:Factory/.python-rpyc.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-rpyc"
Wed Jan 3 12:24:07 2024 rev:13 rq:1135621 version:5.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-rpyc/python-rpyc.changes 2023-02-28 12:49:43.772868522 +0100
+++ /work/SRC/openSUSE:Factory/.python-rpyc.new.28375/python-rpyc.changes 2024-01-03 12:24:13.041787825 +0100
@@ -1,0 +2,11 @@
+Fri Dec 29 09:53:28 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 5.3.1:
+ * `#527`_ Resolved timeout issue that was introduced in 5.2.1
+ * `#525`_ and `#524`_ Fixed experimental thread binding struct
+ for platforms where unsigned long is 8-bits
+ While the fix for thread binding is not backwards compatible,
+ it only impacts people using an experimental feature. Hence,
+ I did a patch version bump.
+
+-------------------------------------------------------------------
Old:
----
5.3.0.tar.gz
New:
----
5.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-rpyc.spec ++++++
--- /var/tmp/diff_new_pack.Jb2zIt/_old 2024-01-03 12:24:13.681811209 +0100
+++ /var/tmp/diff_new_pack.Jb2zIt/_new 2024-01-03 12:24:13.681811209 +0100
@@ -24,9 +24,9 @@
%define psuffix %{nil}
%bcond_with test
%endif
-%global skip_python2 1
+%{?sle15_python_module_pythons}
Name: python-rpyc%{psuffix}
-Version: 5.3.0
+Version: 5.3.1
Release: 0
Summary: Remote Python Call (RPyC), a RPC library
License: MIT
@@ -100,6 +100,6 @@
%python_alternative %{_bindir}/rpyc_classic
%python_alternative %{_bindir}/rpyc_registry
%{python_sitelib}/rpyc
-%{python_sitelib}/rpyc-%{version}*-info
+%{python_sitelib}/rpyc-%{version}.dist-info
%endif
++++++ 5.3.0.tar.gz -> 5.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpyc-5.3.0/CHANGELOG.rst new/rpyc-5.3.1/CHANGELOG.rst
--- old/rpyc-5.3.0/CHANGELOG.rst 2022-11-26 07:09:01.000000000 +0100
+++ new/rpyc-5.3.1/CHANGELOG.rst 2023-02-22 04:42:03.000000000 +0100
@@ -1,3 +1,17 @@
+5.3.1
+=====
+Date: 2023-02-21
+
+- `#527`_ Resolved timeout issue that was introduced in 5.2.1
+- `#525`_ and `#524`_ Fixed experimental thread binding struct for platforms where unsigned long is 8-bits
+
+ - While the fix for thread binding is not backwards compatible, it only impacts people using an experimental feature. Hence, I did a patch version bump.
+
+.. _#525: https://github.com/tomerfiliba-org/rpyc/pull/525
+.. _#524: https://github.com/tomerfiliba-org/rpyc/issues/524
+.. _#527: https://github.com/tomerfiliba-org/rpyc/issues/527
+
+
5.3.0
=====
Date: 2022-11-25
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpyc-5.3.0/docs/conf.py new/rpyc-5.3.1/docs/conf.py
--- old/rpyc-5.3.0/docs/conf.py 2022-11-26 07:09:01.000000000 +0100
+++ new/rpyc-5.3.1/docs/conf.py 2023-02-22 04:42:03.000000000 +0100
@@ -11,7 +11,6 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-from rpyc.version import __version__, release_date
import sys
import os
import time
@@ -52,6 +51,7 @@
# built documents.
#
# The short X.Y version.
+from rpyc.version import __version__, release_date
version = __version__
# The full version, including alpha/beta/rc tags.
release = __version__ + "/" + release_date
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpyc-5.3.0/rpyc/core/brine.py new/rpyc-5.3.1/rpyc/core/brine.py
--- old/rpyc-5.3.0/rpyc/core/brine.py 2022-11-26 07:09:01.000000000 +0100
+++ new/rpyc-5.3.1/rpyc/core/brine.py 2023-02-22 04:42:03.000000000 +0100
@@ -56,9 +56,13 @@
C16 = Struct("!dd") # Successive floats (complex numbers)
I1 = Struct("!B") # Python type int w/ size [1] (ctype unsigned char)
I4 = Struct("!L") # Python type int w/ size [4] (ctype unsigned long)
-# I4I4 is successive ints w/ size 4 and was introduced to pack local thread id and remote thread id
-# Since PyThread_get_thread_ident returns a type of unsigned long, !LL can store both thread IDs.
-I4I4 = Struct("!LL")
+# I8I8 is successive ints w/ size 8 and was introduced to pack local thread id and remote thread id. Since
+# PyThread_get_thread_ident returns a type of unsigned long, a platform dependent size, we
+# need 8 bytes of length to support LP64/64-bit platforms. See
+# - https://unix.org/whitepapers/64bit.html
+# - https://en.wikipedia.org/wiki/Integer_(computer_science)#Long_integer
+# TODO: Switch to native_id when 3.7 is EOL b/c PyThread_get_thread_ident is inheritly hosed due to casting.
+I8I8 = Struct("!QQ")
_dump_registry = {}
_load_registry = {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpyc-5.3.0/rpyc/core/protocol.py new/rpyc-5.3.1/rpyc/core/protocol.py
--- old/rpyc-5.3.0/rpyc/core/protocol.py 2022-11-26 07:09:01.000000000 +0100
+++ new/rpyc-5.3.1/rpyc/core/protocol.py 2023-02-22 04:42:03.000000000 +0100
@@ -24,6 +24,7 @@
pass
+UNBOUND_THREAD_ID = 0 # Used when the message is being sent but the thread is not bound yet.
DEFAULT_CONFIG = dict(
# ATTRIBUTES
allow_safe_attrs=True,
@@ -171,7 +172,9 @@
self._send_queue = []
self._local_root = root
self._closed = False
+ # Settings for bind_threads
self._bind_threads = self._config['bind_threads']
+ self._threads = None
if self._bind_threads:
self._lock = threading.Lock()
self._threads = {}
@@ -260,13 +263,13 @@
data = brine.dump((msg, seq, args))
if self._bind_threads:
this_thread = self._get_thread()
- data = brine.I4I4.pack(this_thread.id, this_thread._remote_thread_id) + data
+ data = brine.I8I8.pack(this_thread.id, this_thread._remote_thread_id) + data
if msg == consts.MSG_REQUEST:
this_thread._occupation_count += 1
else:
this_thread._occupation_count -= 1
if this_thread._occupation_count == 0:
- this_thread._remote_thread_id = 0
+ this_thread._remote_thread_id = UNBOUND_THREAD_ID
# GC might run while sending data
# if so, a BaseNetref.__del__ might be called
# BaseNetref.__del__ must call asyncreq,
@@ -399,7 +402,7 @@
this_thread = self._get_thread()
this_thread._occupation_count -= 1
if this_thread._occupation_count == 0:
- this_thread._remote_thread_id = 0
+ this_thread._remote_thread_id = UNBOUND_THREAD_ID
if msg == consts.MSG_REPLY:
obj = self._unbox(args)
self._seq_request_callback(msg, seq, False, obj)
@@ -429,27 +432,25 @@
else:
return False
# Assume the receive rlock is acquired and incremented
+ # We must release once BEFORE dispatch, dispatch any data, and THEN notify all (see issue #527 and #449)
try:
data = None # Ensure data is initialized
data = self._channel.poll(timeout) and self._channel.recv()
except Exception as exc:
+ self._recvlock.release()
if isinstance(exc, EOFError):
self.close() # sends close async request
- self._recvlock.release()
- with self._recv_event:
- self._recv_event.notify_all()
raise
- # At this point, the recvlock was acquired once, we must release once before exiting the function
- if data:
- # Dispatch will unbox, invoke callbacks, etc.
- self._dispatch(data)
+ else:
self._recvlock.release()
+ if data:
+ self._dispatch(data) # Dispatch will unbox, invoke callbacks, etc.
+ return True
+ else:
+ return False
+ finally:
with self._recv_event:
self._recv_event.notify_all()
- return True
- else:
- self._recvlock.release()
- return False
def _serve_bound(self, timeout, wait_for_lock):
"""Serves messages like `serve` with the added benefit of making request/reply thread bound.
@@ -549,35 +550,34 @@
return False
- remote_thread_id, local_thread_id = brine.I4I4.unpack(message[:16])
+ remote_thread_id, local_thread_id = brine.I8I8.unpack(message[:16])
message = message[16:]
this = False
- if local_thread_id == 0: # root request
- if this_thread._occupation_count == 0: # this
- this = True
-
- else: # other
- new = False
-
- with self._lock:
- for thread in self._thread_pool:
- if thread._occupation_count == 0 and not thread._event.is_set():
- thread._deque.append((remote_thread_id, message))
- thread._event.set()
- break
+ if local_thread_id == UNBOUND_THREAD_ID and this_thread._occupation_count != 0:
+ # Message is not meant for this thread. Use a thread that is not occupied or have the pool create a new one.
+ # TODO: reusing threads may be problematic if occupation being zero is wrong...
+ new = False
+ with self._lock:
+ for thread in self._thread_pool:
+ if thread._occupation_count == 0 and not thread._event.is_set():
+ thread._deque.append((remote_thread_id, message))
+ thread._event.set()
+ break
- else:
- new = True
+ else:
+ new = True
- if new:
- self._thread_pool_executor.submit(self._serve_temporary, remote_thread_id, message)
+ if new:
+ self._thread_pool_executor.submit(self._serve_temporary, remote_thread_id, message)
- elif local_thread_id == this_thread.id:
+ elif local_thread_id in {UNBOUND_THREAD_ID, this_thread.id}:
+ # Of course, the message is for this thread if equal. When id is UNBOUND_THREAD_ID,
+ # we deduce that occupation count is 0 from the previous if condition. So, set this True.
this = True
-
- else: # sub request
+ else:
+ # Otherwise, message was meant for another thread.
thread = self._get_thread(id=local_thread_id)
with self._lock:
thread._deque.append((remote_thread_id, message))
@@ -924,7 +924,7 @@
self.id = id
- self._remote_thread_id = 0
+ self._remote_thread_id = UNBOUND_THREAD_ID
self._occupation_count = 0
self._event = threading.Event()
self._deque = collections.deque()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpyc-5.3.0/rpyc/version.py new/rpyc-5.3.1/rpyc/version.py
--- old/rpyc-5.3.0/rpyc/version.py 2022-11-26 07:09:01.000000000 +0100
+++ new/rpyc-5.3.1/rpyc/version.py 2023-02-22 04:42:03.000000000 +0100
@@ -1,3 +1,3 @@
-__version__ = '5.3.0'
+__version__ = '5.3.1'
version = tuple(__version__.split('.'))
-release_date = "2022-11-25"
+release_date = "2023-02-21"
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-rope for openSUSE:Factory checked in at 2024-01-03 12:24:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-rope (Old)
and /work/SRC/openSUSE:Factory/.python-rope.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-rope"
Wed Jan 3 12:24:06 2024 rev:32 rq:1135620 version:1.11.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-rope/python-rope.changes 2023-11-09 21:35:55.098038001 +0100
+++ /work/SRC/openSUSE:Factory/.python-rope.new.28375/python-rope.changes 2024-01-03 12:24:10.937710947 +0100
@@ -1,0 +2,13 @@
+Fri Dec 29 09:51:08 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 1.11.0:
+ * #710, #561 Implement `except*` syntax
+ * #711 allow building documentation without having rope module
+ installed
+ * #719 Allows the in-memory db to be shared across threads
+ * #720 create one sqlite3.Connection per thread using a thread
+ local
+ * #715 change AutoImport's `get_modules` to be case sensitive
+ * #708, #709 Add support for Python 3.12 (@lieryan)
+
+-------------------------------------------------------------------
Old:
----
rope-1.9.0.tar.gz
New:
----
rope-1.11.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-rope.spec ++++++
--- /var/tmp/diff_new_pack.eK3Ffc/_old 2024-01-03 12:24:11.997749679 +0100
+++ /var/tmp/diff_new_pack.eK3Ffc/_new 2024-01-03 12:24:11.997749679 +0100
@@ -17,10 +17,8 @@
%{?sle15_python_module_pythons}
-
-%define upname rope
Name: python-rope
-Version: 1.9.0
+Version: 1.11.0
Release: 0
Summary: A python refactoring library
License: LGPL-3.0-or-later
@@ -29,7 +27,6 @@
Source: https://files.pythonhosted.org/packages/source/r/rope/rope-%{version}.tar.gz
BuildRequires: %{python_module base >= 3.7}
BuildRequires: %{python_module pip}
-BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module wheel}
# SECTION test
# Requires full stdlib
++++++ rope-1.9.0.tar.gz -> rope-1.11.0.tar.gz ++++++
++++ 1927 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-sphinxcontrib-plantuml for openSUSE:Factory checked in at 2024-01-03 12:24:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sphinxcontrib-plantuml (Old)
and /work/SRC/openSUSE:Factory/.python-sphinxcontrib-plantuml.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sphinxcontrib-plantuml"
Wed Jan 3 12:24:04 2024 rev:7 rq:1135617 version:0.27
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-sphinxcontrib-plantuml/python-sphinxcontrib-plantuml.changes 2022-12-06 14:23:10.717526166 +0100
+++ /work/SRC/openSUSE:Factory/.python-sphinxcontrib-plantuml.new.28375/python-sphinxcontrib-plantuml.changes 2024-01-03 12:24:08.901636554 +0100
@@ -1,0 +2,9 @@
+Fri Dec 29 09:49:50 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 0.27:
+ * add svg width height properties, override SVG style
+ * reformat sources with black, adjust flake8 rules accordingly
+ * remove redundant wheel dep from pyproject.toml
+ * create output file with unique file name
+
+-------------------------------------------------------------------
Old:
----
sphinxcontrib-plantuml-0.24.1.tar.gz
New:
----
sphinxcontrib-plantuml-0.27.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-sphinxcontrib-plantuml.spec ++++++
--- /var/tmp/diff_new_pack.13ucLW/_old 2024-01-03 12:24:09.805669585 +0100
+++ /var/tmp/diff_new_pack.13ucLW/_new 2024-01-03 12:24:09.805669585 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-sphinxcontrib-plantuml
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,11 +16,9 @@
#
-%define skip_python2 1
-%{?!python_module:%define python_module() python3-%{**}}
-
+%{?sle15_python_module_pythons}
Name: python-sphinxcontrib-plantuml
-Version: 0.24.1
+Version: 0.27
Release: 0
Summary: Sphinx API for Web Apps
License: BSD-2-Clause
@@ -30,8 +28,9 @@
Patch0: py3-for-tests.patch
BuildRequires: %{python_module Sphinx >= 2}
BuildRequires: %{python_module Sphinx-latex}
+BuildRequires: %{python_module pip}
BuildRequires: %{python_module pytest}
-BuildRequires: %{python_module setuptools}
+BuildRequires: %{python_module wheel}
BuildRequires: fdupes
BuildRequires: ghostscript
BuildRequires: python-rpm-macros
@@ -54,10 +53,10 @@
%patch0 -p1
%build
-%python_build
+%pyproject_wheel
%install
-%python_install
+%pyproject_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
@@ -72,5 +71,5 @@
%pycache_only %{python_sitelib}/sphinxcontrib/__pycache__
%{python_sitelib}/sphinxcontrib/plantuml.*
%{python_sitelib}/sphinxcontrib_plantuml-%{version}-py*-nspkg.pth
-%{python_sitelib}/sphinxcontrib_plantuml-%{version}-py*.*-info
+%{python_sitelib}/sphinxcontrib_plantuml-%{version}.dist-info
++++++ sphinxcontrib-plantuml-0.24.1.tar.gz -> sphinxcontrib-plantuml-0.27.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/plantuml-0.24.1/pyproject.toml new/plantuml-0.27/pyproject.toml
--- old/plantuml-0.24.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100
+++ new/plantuml-0.27/pyproject.toml 2023-10-31 10:36:11.000000000 +0100
@@ -0,0 +1,6 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[tool.black]
+skip-string-normalization = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/plantuml-0.24.1/setup.cfg new/plantuml-0.27/setup.cfg
--- old/plantuml-0.24.1/setup.cfg 2022-11-18 04:35:48.000000000 +0100
+++ new/plantuml-0.27/setup.cfg 2023-10-31 10:36:11.000000000 +0100
@@ -8,10 +8,12 @@
[flake8]
exclude =
tests/fixture
+# E203: whitespace before ':' (which disagrees with black)
# E741: ambiguous variable name 'l'
# W503: line break before binary operator
-ignore = E741, W503
-max-line-length = 80
+ignore = E203, E741, W503
+# The default of black
+max-line-length = 88
[options]
install_requires =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/plantuml-0.24.1/setup.py new/plantuml-0.27/setup.py
--- old/plantuml-0.24.1/setup.py 2022-11-18 04:35:48.000000000 +0100
+++ new/plantuml-0.27/setup.py 2023-10-31 10:36:11.000000000 +0100
@@ -6,7 +6,7 @@
setup(
name='sphinxcontrib-plantuml',
- version='0.24.1',
+ version='0.27',
url='https://github.com/sphinx-contrib/plantuml/',
download_url='https://pypi.python.org/pypi/sphinxcontrib-plantuml',
license='BSD',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/plantuml-0.24.1/sphinxcontrib/plantuml.py new/plantuml-0.27/sphinxcontrib/plantuml.py
--- old/plantuml-0.24.1/sphinxcontrib/plantuml.py 2022-11-18 04:35:48.000000000 +0100
+++ new/plantuml-0.27/sphinxcontrib/plantuml.py 2023-10-31 10:36:11.000000000 +0100
@@ -17,6 +17,7 @@
import shlex
import shutil
import subprocess
+import tempfile
from contextlib import contextmanager
from docutils import nodes
@@ -44,6 +45,7 @@
if os.name == 'nt':
+
def rename(src, dst):
try:
os.rename(src, dst)
@@ -52,6 +54,7 @@
raise
os.unlink(dst)
os.rename(src, dst)
+
else:
rename = os.rename
@@ -90,6 +93,7 @@
Alice -> Bob: Hello
Alice <- Bob: Hi
"""
+
has_content = True
required_arguments = 0
optional_arguments = 1
@@ -104,14 +108,19 @@
'name': directives.unchanged,
'scale': directives.percentage,
'width': directives.length_or_percentage_or_unitless,
+ 'max-width': directives.length_or_percentage_or_unitless,
}
def run(self):
warning = self.state.document.reporter.warning
env = self.state.document.settings.env
if self.arguments and self.content:
- return [warning('uml directive cannot have both content and '
- 'a filename argument', line=self.lineno)]
+ return [
+ warning(
+ 'uml directive cannot have both content and ' 'a filename argument',
+ line=self.lineno,
+ )
+ ]
if self.arguments:
fn = i18n.search_image_for_language(self.arguments[0], env)
relfn, absfn = env.relfn2path(fn)
@@ -119,8 +128,12 @@
try:
umlcode = _read_utf8(absfn)
except (IOError, UnicodeDecodeError) as err:
- return [warning('PlantUML file "%s" cannot be read: %s'
- % (fn, err), line=self.lineno)]
+ return [
+ warning(
+ 'PlantUML file "%s" cannot be read: %s' % (fn, err),
+ line=self.lineno,
+ )
+ ]
else:
relfn = env.doc2path(env.docname, base=None)
umlcode = '\n'.join(self.content)
@@ -137,8 +150,9 @@
if 'align' in self.options:
node['align'] = self.options['align']
if 'caption' in self.options:
- inodes, messages = self.state.inline_text(self.options['caption'],
- self.lineno)
+ inodes, messages = self.state.inline_text(
+ self.options['caption'], self.lineno
+ )
caption_node = nodes.caption(self.options['caption'], '', *inodes)
caption_node.extend(messages)
set_source_info(self, caption_node)
@@ -174,8 +188,10 @@
fname = 'plantuml-%s.%s' % (key, fileformat)
imgpath = getattr(self.builder, 'imgpath', None)
if imgpath:
- return ('/'.join((self.builder.imgpath, fname)),
- os.path.join(self.builder.outdir, '_images', fname))
+ return (
+ '/'.join((self.builder.imgpath, fname)),
+ os.path.join(self.builder.outdir, '_images', fname),
+ )
else:
return fname, os.path.join(self.builder.outdir, fname)
@@ -227,16 +243,19 @@
def render_plantuml_inline(self, node, fileformat):
absincdir = os.path.join(self.builder.srcdir, node['incdir'])
try:
- p = subprocess.Popen(generate_plantuml_args(self, node, fileformat),
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- cwd=absincdir)
+ p = subprocess.Popen(
+ generate_plantuml_args(self, node, fileformat),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=absincdir,
+ )
except OSError as err:
if err.errno != errno.ENOENT:
raise
- raise PlantUmlError('plantuml command %r cannot be run'
- % self.builder.config.plantuml)
+ raise PlantUmlError(
+ 'plantuml command %r cannot be run' % self.builder.config.plantuml
+ )
sout, serr = p.communicate(node['uml'].encode('utf-8'))
if p.returncode != 0:
raise PlantUmlError('error while running plantuml\n\n%s' % serr)
@@ -250,8 +269,9 @@
self.builder = builder
self.batch_size = builder.config.plantuml_batch_size
- self.cache_dir = os.path.join(builder.outdir,
- builder.config.plantuml_cache_path)
+ self.cache_dir = os.path.join(
+ builder.outdir, builder.config.plantuml_cache_path
+ )
self._base_cmdargs = _split_cmdargs(builder.config.plantuml)
self._base_cmdargs.extend(['-charset', 'utf-8'])
@@ -286,8 +306,10 @@
outdir = os.path.join(self.cache_dir, key[:2])
outfbase = os.path.join(outdir, key)
- if all(os.path.exists('%s.%s' % (outfbase, sfx))
- for sfx in ['puml'] + self.image_formats):
+ if all(
+ os.path.exists('%s.%s' % (outfbase, sfx))
+ for sfx in ['puml'] + self.image_formats
+ ):
continue
ensuredir(outdir)
@@ -308,10 +330,11 @@
pending_keys = sorted(self._pending_keys)
for fileformat in self.image_formats:
for i in range(0, len(pending_keys), self.batch_size):
- keys = pending_keys[i:i + self.batch_size]
+ keys = pending_keys[i : i + self.batch_size]
with util.progress_message(
- 'rendering plantuml diagrams [%d..%d/%d]'
- % (i, i + len(keys), len(pending_keys))):
+ 'rendering plantuml diagrams [%d..%d/%d]'
+ % (i, i + len(keys), len(pending_keys))
+ ):
self._render_files(keys, fileformat)
del self._pending_keys[:]
@@ -321,50 +344,67 @@
cmdargs.extend(_ARGS_BY_FILEFORMAT[fileformat])
cmdargs.extend(os.path.join(k[:2], '%s.puml' % k) for k in keys)
try:
- p = subprocess.Popen(cmdargs, stderr=subprocess.PIPE,
- cwd=self.cache_dir)
+ p = subprocess.Popen(cmdargs, stderr=subprocess.PIPE, cwd=self.cache_dir)
except OSError as err:
if err.errno != errno.ENOENT:
raise
- raise PlantUmlError('plantuml command %r cannot be run'
- % self.builder.config.plantuml)
+ raise PlantUmlError(
+ 'plantuml command %r cannot be run' % self.builder.config.plantuml
+ )
serr = p.communicate()[1]
if p.returncode != 0:
if self.builder.config.plantuml_syntax_error_image:
- logger.warning('error while running plantuml\n\n%s' % serr)
+ logger.warning(
+ 'error while running plantuml\n\n%s' % serr, type='plantuml'
+ )
else:
raise PlantUmlError('error while running plantuml\n\n%s' % serr)
def render(self, node, fileformat):
key = hash_plantuml_node(node)
outdir = os.path.join(self.cache_dir, key[:2])
- outfname = os.path.join(outdir, '%s.%s' % (key, fileformat))
+ basename = '%s.%s' % (key, fileformat)
+ outfname = os.path.join(outdir, basename)
if os.path.exists(outfname):
return outfname
ensuredir(outdir)
absincdir = os.path.join(self.builder.srcdir, node['incdir'])
- with open(outfname + '.new', 'wb') as f:
+ # TODO: delete_on_close can be used on Python 3.12+
+ with tempfile.NamedTemporaryFile(
+ prefix=basename + '.new', dir=outdir, delete=False
+ ) as f:
try:
- p = subprocess.Popen(generate_plantuml_args(self, node,
- fileformat),
- stdout=f, stdin=subprocess.PIPE,
- stderr=subprocess.PIPE,
- cwd=absincdir)
+ p = subprocess.Popen(
+ generate_plantuml_args(self, node, fileformat),
+ stdout=f,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=absincdir,
+ )
except OSError as err:
if err.errno != errno.ENOENT:
raise
- raise PlantUmlError('plantuml command %r cannot be run'
- % self.builder.config.plantuml)
+ raise PlantUmlError(
+ 'plantuml command %r cannot be run' % self.builder.config.plantuml
+ )
serr = p.communicate(node['uml'].encode('utf-8'))[1]
if p.returncode != 0:
if self.builder.config.plantuml_syntax_error_image:
- logger.warning('error while running plantuml\n\n%s' % serr)
+ logger.warning(
+ 'error while running plantuml\n\n%s' % serr,
+ location=node,
+ type='plantuml',
+ )
else:
- raise PlantUmlError('error while running plantuml\n\n%s'
- % serr)
+ raise PlantUmlError('error while running plantuml\n\n%s' % serr)
+
+ # inherit dir mode since temp file isn't world-readable by default.
+ if os.name == 'posix':
+ os.fchmod(f.fileno(), os.lstat(outdir).st_mode & 0o666)
+ f.close()
+ rename(f.name, outfname)
- rename(outfname + '.new', outfname)
return outfname
@@ -380,12 +420,16 @@
# process images prior to html_vist.
scale_attrs = [k for k in ('scale', 'width', 'height') if k in node]
if scale_attrs and Image is None:
- logger.warning(('plantuml: unsupported scaling attributes: %s '
- '(install PIL or Pillow)'
- % ', '.join(scale_attrs)))
+ logger.warning(
+ (
+ 'plantuml: unsupported scaling attributes: %s '
+ '(install PIL or Pillow)' % ', '.join(scale_attrs)
+ ),
+ location=node,
+ type='plantuml',
+ )
if not scale_attrs or Image is None:
- return ('<img src="%s" alt="%s"/>\n'
- % (self.encode(refname), self.encode(alt)))
+ return '<img src="%s" alt="%s"/>\n' % (self.encode(refname), self.encode(alt))
scale = node.get('scale', 100)
styles = []
@@ -410,17 +454,23 @@
try:
im = Image.open(outfname)
im.load()
- styles.extend('%s: %s%s' % (a, w * scale / 100, 'px')
- for a, w in zip(['width', 'height'], im.size))
+ styles.extend(
+ '%s: %s%s' % (a, w * scale / 100, 'px')
+ for a, w in zip(['width', 'height'], im.size)
+ )
except (IOError, OSError) as err:
- logger.warning('plantuml: failed to get image size: %s' % err)
-
- return ('<a href="%s"><img src="%s" alt="%s" style="%s"/>'
- '</a>\n'
- % (self.encode(refname),
- self.encode(refname),
- self.encode(alt),
- self.encode('; '.join(styles))))
+ logger.warning(
+ 'plantuml: failed to get image size: %s' % err,
+ location=node,
+ type='plantuml',
+ )
+
+ return '<a href="%s"><img src="%s" alt="%s" style="%s"/>' '</a>\n' % (
+ self.encode(refname),
+ self.encode(refname),
+ self.encode(alt),
+ self.encode('; '.join(styles)),
+ )
def _get_svg_style(fname):
@@ -442,30 +492,48 @@
return m.group(1)
+def _svg_get_style_str(node, outfname):
+ width_height_styles = [
+ "%s:%s" % (key, val)
+ for key, val in node.attributes.items()
+ if key in ['width', 'height', 'max-width']
+ ]
+ if width_height_styles:
+ style_str = '; '.join(width_height_styles)
+ else:
+ style_str = _get_svg_style(outfname) or ''
+ return style_str
+
+
def _get_svg_tag(self, fnames, node):
refname, outfname = fnames['svg']
- return '\n'.join([
- # copy width/height style from <svg> tag, so that <object> area
- # has enough space.
- '<object data="%s" type="image/svg+xml" style="%s">' % (
- self.encode(refname), _get_svg_style(outfname) or ''),
- _get_png_tag(self, fnames, node),
- '</object>'])
+ style_str = _svg_get_style_str(node, outfname)
+ return '\n'.join(
+ [
+ # copy width/height style from <svg> tag, so that <object> area
+ # has enough space.
+ '<object data="%s" type="image/svg+xml" style="%s">'
+ % (self.encode(refname), style_str),
+ _get_png_tag(self, fnames, node),
+ '</object>',
+ ]
+ )
def _get_svg_img_tag(self, fnames, node):
refname, outfname = fnames['svg']
alt = node.get('alt', node['uml'])
- return ('<img src="%s" alt="%s"/>'
- % (self.encode(refname), self.encode(alt)))
+ return '<img src="%s" alt="%s"/>' % (self.encode(refname), self.encode(alt))
def _get_svg_obj_tag(self, fnames, node):
refname, outfname = fnames['svg']
# copy width/height style from <svg> tag, so that <object> area
# has enough space.
- return ('<object data="%s" type="image/svg+xml" style="%s"></object>'
- % (self.encode(refname), _get_svg_style(outfname) or ''))
+ return '<object data="%s" type="image/svg+xml" style="%s"></object>' % (
+ self.encode(refname),
+ _get_svg_style(outfname) or '',
+ )
_KNOWN_HTML_FORMATS = {
@@ -482,18 +550,19 @@
except KeyError:
raise PlantUmlError(
'plantuml_output_format must be one of %s, but is %r'
- % (', '.join(map(repr, _KNOWN_HTML_FORMATS)), fmt))
+ % (', '.join(map(repr, _KNOWN_HTML_FORMATS)), fmt)
+ )
@contextmanager
-def _prepare_html_render(self, fmt):
+def _prepare_html_render(self, fmt, node):
if fmt == 'none':
raise nodes.SkipNode
try:
yield _lookup_html_format(fmt)
except PlantUmlError as err:
- logger.warning(str(err))
+ logger.warning(str(err), location=node, type='plantuml')
raise nodes.SkipNode
@@ -504,10 +573,9 @@
else:
fmt = self.builder.config.plantuml_output_format
- with _prepare_html_render(self, fmt) as (fileformats, gettag):
+ with _prepare_html_render(self, fmt, node) as (fileformats, gettag):
# fnames: {fileformat: (refname, outfname), ...}
- fnames = dict((e, render_plantuml(self, node, e))
- for e in fileformats)
+ fnames = dict((e, render_plantuml(self, node, e)) for e in fileformats)
self.body.append(self.starttag(node, 'p', CLASS='plantuml'))
self.body.append(gettag(self, fnames, node))
@@ -520,19 +588,20 @@
args.append(fname)
try:
try:
- p = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError as err:
# workaround for missing shebang of epstopdf script
if err.errno != getattr(errno, 'ENOEXEC', 0):
raise
- p = subprocess.Popen(['bash'] + args, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ p = subprocess.Popen(
+ ['bash'] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
except OSError as err:
if err.errno != errno.ENOENT:
raise
- raise PlantUmlError('epstopdf command %r cannot be run'
- % self.builder.config.plantuml_epstopdf)
+ raise PlantUmlError(
+ 'epstopdf command %r cannot be run' % self.builder.config.plantuml_epstopdf
+ )
serr = p.communicate()[1]
if p.returncode != 0:
raise PlantUmlError('error while running epstopdf\n\n%s' % serr)
@@ -553,7 +622,8 @@
except KeyError:
raise PlantUmlError(
'plantuml_latex_output_format must be one of %s, but is %r'
- % (', '.join(map(repr, _KNOWN_LATEX_FORMATS)), fmt))
+ % (', '.join(map(repr, _KNOWN_LATEX_FORMATS)), fmt)
+ )
def _latex_adjustbox_options(self, node):
@@ -574,8 +644,7 @@
adjustbox_options.append('height=%s' % h)
if 'scale' in node:
if not adjustbox_options:
- adjustbox_options.append('scale=%s'
- % (float(node['scale']) / 100.0))
+ adjustbox_options.append('scale=%s' % (float(node['scale']) / 100.0))
return adjustbox_options
@@ -600,7 +669,7 @@
refname, outfname = render_plantuml(self, node, fileformat)
refname, outfname = postproc(self, refname, outfname)
except PlantUmlError as err:
- logger.warning(str(err))
+ logger.warning(str(err), location=node, type='plantuml')
raise nodes.SkipNode
if fmt == 'tikz':
@@ -644,7 +713,8 @@
if fmt not in _KNOWN_CONFLUENCE_FORMATS:
raise PlantUmlError(
'plantuml_output_format must be one of %s, but is %r'
- % (', '.join(map(repr, _KNOWN_CONFLUENCE_FORMATS)), fmt))
+ % (', '.join(map(repr, _KNOWN_CONFLUENCE_FORMATS)), fmt)
+ )
_, outfname = render_plantuml(self, node, fmt)
@@ -663,7 +733,7 @@
try:
text = render_plantuml_inline(self, node, 'txt')
except PlantUmlError as err:
- logger.warning(str(err))
+ logger.warning(str(err), location=node, type='plantuml')
text = node['uml'] # fall back to uml text, which is still readable
self.new_state()
@@ -678,14 +748,18 @@
refname, outfname = render_plantuml(self, node, 'eps')
refname, outfname = _convert_eps_to_pdf(self, refname, outfname)
except PlantUmlError as err:
- logger.warning(str(err))
+ logger.warning(str(err), location=node, type='plantuml')
raise nodes.SkipNode
rep = nodes.image(uri=outfname, alt=node.get('alt', node['uml']))
node.parent.replace(node, rep)
def unsupported_visit_plantuml(self, node):
- logger.warning('plantuml: unsupported output format (node skipped)')
+ logger.warning(
+ 'plantuml: unsupported output format (node skipped)',
+ location=node,
+ type='plantuml',
+ )
raise nodes.SkipNode
@@ -723,8 +797,7 @@
app.add_node(plantuml, **_NODE_VISITORS)
app.add_directive('uml', UmlDirective)
try:
- app.add_config_value('plantuml', 'plantuml', 'html',
- types=(str, tuple, list))
+ app.add_config_value('plantuml', 'plantuml', 'html', types=(str, tuple, list))
except TypeError:
# Sphinx < 1.4?
app.add_config_value('plantuml', 'plantuml', 'html')
@@ -741,6 +814,7 @@
# imitate what app.add_node() does
if 'rst2pdf.pdfbuilder' in app.config.extensions:
from rst2pdf.pdfbuilder import PDFTranslator as translator
+
setattr(translator, 'visit_' + plantuml.__name__, pdf_visit_plantuml)
return {'parallel_read_safe': True}
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-weblate-language-data for openSUSE:Factory checked in at 2024-01-03 12:24:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-weblate-language-data (Old)
and /work/SRC/openSUSE:Factory/.python-weblate-language-data.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-weblate-language-data"
Wed Jan 3 12:24:03 2024 rev:6 rq:1135613 version:2023.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-weblate-language-data/python-weblate-language-data.changes 2022-12-15 19:24:53.771950821 +0100
+++ /work/SRC/openSUSE:Factory/.python-weblate-language-data.new.28375/python-weblate-language-data.changes 2024-01-03 12:24:06.173536874 +0100
@@ -1,0 +2,6 @@
+Fri Dec 29 09:39:56 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 2023.9:
+ * translation updates
+
+-------------------------------------------------------------------
Old:
----
weblate-language-data-2022.9.tar.gz
New:
----
weblate-language-data-2023.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-weblate-language-data.spec ++++++
--- /var/tmp/diff_new_pack.jigK0v/_old 2024-01-03 12:24:07.481584669 +0100
+++ /var/tmp/diff_new_pack.jigK0v/_new 2024-01-03 12:24:07.481584669 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-weblate-language-data
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -20,14 +20,15 @@
%define modname weblate-language-data
%define skip_python2 1
Name: python-weblate-language-data
-Version: 2022.9
+Version: 2023.9
Release: 0
Summary: Language Data for Weblate
License: MIT
URL: https://github.com/WeblateOrg/language-data
Source0: https://files.pythonhosted.org/packages/source/w/%{modname}/%{modname}-%{ve…
-BuildRequires: %{python_module setuptools}
+BuildRequires: %{python_module pip}
BuildRequires: %{python_module translate-toolkit >= 3.1}
+BuildRequires: %{python_module wheel}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
BuildArch: noarch
@@ -42,14 +43,15 @@
%setup -q -n %{modname}-%{version}
%build
-%python_build
+%pyproject_wheel
%install
-%python_install
+%pyproject_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}/weblate_language_data
%files %{python_files}
%license LICENSE
%doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/weblate_language_data
+%{python_sitelib}/weblate_language_data-%{version}.dist-info
++++++ weblate-language-data-2022.9.tar.gz -> weblate-language-data-2023.9.tar.gz ++++++
++++ 122509 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-recordclass for openSUSE:Factory checked in at 2024-01-03 12:24:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-recordclass (Old)
and /work/SRC/openSUSE:Factory/.python-recordclass.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-recordclass"
Wed Jan 3 12:24:01 2024 rev:4 rq:1135612 version:0.21.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-recordclass/python-recordclass.changes 2022-11-12 17:41:20.406229053 +0100
+++ /work/SRC/openSUSE:Factory/.python-recordclass.new.28375/python-recordclass.changes 2024-01-03 12:24:04.109461459 +0100
@@ -1,0 +2,11 @@
+Fri Dec 29 09:35:17 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 0.21.1:
+ * Allow to specify __match_args__.
+ * Add @as_record adapter for def-style decalarations of
+ dataclasses that are considered as just a struct.
+ * The option fast_new will be removed in 0.22. It will be
+ always as fast_new=True by creation.
+ * Fix issues with `_PyUnicodeWriter` for python 3.13.
+
+-------------------------------------------------------------------
Old:
----
recordclass-0.18.0.1.tar.gz
New:
----
recordclass-0.21.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-recordclass.spec ++++++
--- /var/tmp/diff_new_pack.jvhVUR/_old 2024-01-03 12:24:04.985493467 +0100
+++ /var/tmp/diff_new_pack.jvhVUR/_new 2024-01-03 12:24:04.985493467 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-recordclass
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,11 +18,11 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-recordclass
-Version: 0.18.0.1
+Version: 0.21.1
Release: 0
Summary: Library implementing a mutable variant of namedtuple
License: MIT
-URL: https://bitbucket.org/intellimath/recordclass
+URL: https://github.com/intellimath/recordclass
Source: https://files.pythonhosted.org/packages/source/r/recordclass/recordclass-%{…
BuildRequires: %{python_module devel}
BuildRequires: %{python_module setuptools}
++++++ recordclass-0.18.0.1.tar.gz -> recordclass-0.21.1.tar.gz ++++++
++++ 28823 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-softlayer for openSUSE:Factory checked in at 2024-01-03 12:23:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-softlayer (Old)
and /work/SRC/openSUSE:Factory/.python-softlayer.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-softlayer"
Wed Jan 3 12:23:59 2024 rev:22 rq:1135609 version:6.1.11
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-softlayer/python-softlayer.changes 2023-12-10 10:15:50.127599969 +0100
+++ /work/SRC/openSUSE:Factory/.python-softlayer.new.28375/python-softlayer.changes 2024-01-03 12:24:02.069386920 +0100
@@ -1,0 +2,7 @@
+Fri Dec 29 09:17:14 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 6.1.11:
+ * Added vlan trunks on the server detail page
+ * Added a thread capable client.cf_call() function
+
+-------------------------------------------------------------------
Old:
----
v6.1.10.tar.gz
New:
----
v6.1.11.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-softlayer.spec ++++++
--- /var/tmp/diff_new_pack.jAlJEA/_old 2024-01-03 12:24:03.397435443 +0100
+++ /var/tmp/diff_new_pack.jAlJEA/_new 2024-01-03 12:24:03.397435443 +0100
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-softlayer
-Version: 6.1.10
+Version: 6.1.11
Release: 0
Summary: A set of Python libraries that assist in calling the SoftLayer API
License: MIT
++++++ v6.1.10.tar.gz -> v6.1.11.tar.gz ++++++
++++ 3830 lines of diff (skipped)
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-redfish for openSUSE:Factory checked in at 2024-01-03 12:23:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-redfish (Old)
and /work/SRC/openSUSE:Factory/.python-redfish.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-redfish"
Wed Jan 3 12:23:58 2024 rev:13 rq:1135608 version:3.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-redfish/python-redfish.changes 2022-12-08 16:52:26.683870105 +0100
+++ /work/SRC/openSUSE:Factory/.python-redfish.new.28375/python-redfish.changes 2024-01-03 12:23:59.069277303 +0100
@@ -1,0 +2,14 @@
+Fri Dec 29 09:16:30 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 3.2.1:
+ * Added 'timeout' and 'max_retry' parameters to all REST
+ methods
+ * Added exception to the method when a response contains a
+ message indicating a password change is required
+ * Adding missing newline to M-SEARCH requests
+ * Fixed the inspection of the USN response header from M-SEARCH
+ requests to allow for a multi-digit minor version
+ * Improved usage of the ServerDownOrUnreachableError exception
+ to not lose the original message
+
+-------------------------------------------------------------------
Old:
----
redfish-3.1.8.tar.gz
New:
----
redfish-3.2.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-redfish.spec ++++++
--- /var/tmp/diff_new_pack.QgInhz/_old 2024-01-03 12:24:00.813341026 +0100
+++ /var/tmp/diff_new_pack.QgInhz/_new 2024-01-03 12:24:00.829341611 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-redfish
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
# Copyright (c) 2020-2021, Martin Hauke <mardnh(a)gmx.de>
#
# All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-redfish
-Version: 3.1.8
+Version: 3.2.1
Release: 0
Summary: Redfish Python Library
License: BSD-3-Clause
++++++ redfish-3.1.8.tar.gz -> redfish-3.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/.github/workflows/main.yml new/python-redfish-library-3.2.1/.github/workflows/main.yml
--- old/python-redfish-library-3.1.8/.github/workflows/main.yml 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/.github/workflows/main.yml 2023-08-04 21:42:35.000000000 +0200
@@ -77,7 +77,7 @@
git config user.email "<>"
git add CHANGELOG.md setup.py src/redfish/__init__.py
git commit -s -m "${{github.event.inputs.version}} versioning"
- git push origin master
+ git push origin main
- name: Make the release
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/CHANGELOG.md new/python-redfish-library-3.2.1/CHANGELOG.md
--- old/python-redfish-library-3.1.8/CHANGELOG.md 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/CHANGELOG.md 2023-08-04 21:42:35.000000000 +0200
@@ -1,5 +1,16 @@
# Change Log
+## [3.2.1] - 2023-08-04
+- Added 'timeout' and 'max_retry' parameters to all REST methods
+- Added exception to the method when a response contains a message indicating a password change is required
+
+## [3.2.0] - 2023-07-27
+- Adding missing newline to M-SEARCH requests
+- Fixed the inspection of the USN response header from M-SEARCH requests to allow for a multi-digit minor version
+
+## [3.1.9] - 2023-01-13
+- Improved usage of the ServerDownOrUnreachableError exception to not lose the original message
+
## [3.1.8] - 2022-12-02
- Added request headers to debug log output
- Added redacting of 'Password' properties from request bodies from debug logs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/README.rst new/python-redfish-library-3.2.1/README.rst
--- old/python-redfish-library-3.1.8/README.rst 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/README.rst 2023-08-04 21:42:35.000000000 +0200
@@ -6,7 +6,7 @@
.. image:: https://img.shields.io/github/release/DMTF/python-redfish-library.svg?maxAg…
:target: https://github.com/DMTF/python-redfish-library/releases
.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
- :target: https://raw.githubusercontent.com/DMTF/python-redfish-library/master/LICENSE
+ :target: https://raw.githubusercontent.com/DMTF/python-redfish-library/main/LICENSE
.. image:: https://img.shields.io/pypi/pyversions/redfish.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/redfish
@@ -74,7 +74,7 @@
* ``max_retry``: The number of retries to perform an operation before giving up. The default value is ``10``.
* ``proxies``: A dictionary containing protocol to proxy URL mappings. The default value is ``None``. See `Using proxies`_.
-To crete a Redfish object, call the ``redfish_client`` method:
+To create a Redfish object, call the ``redfish_client`` method:
.. code-block:: python
@@ -97,34 +97,84 @@
~~~~~~~~~~~~~~~~~~~~~~~
A simple GET operation can be performed to obtain the data present in any valid path.
-An example of GET operation on the path "/redfish/v1/systems/1" is shown below:
+An example of GET operation on the path "/redfish/v1/Systems/1" is shown below:
.. code-block:: python
- response = REDFISH_OBJ.get("/redfish/v1/systems/1", None)
+ response = REDFISH_OBJ.get("/redfish/v1/Systems/1")
Perform a POST operation
~~~~~~~~~~~~~~~~~~~~~~~~
A POST operation can be performed to create a resource or perform an action.
-An example of a POST operation on the path "/redfish/v1/systems/1/Actions/ComputerSystem.Reset" is shown below:
+An example of a POST operation on the path "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset" is shown below:
.. code-block:: python
body = {"ResetType": "GracefulShutdown"}
- response = REDFISH_OBJ.post("/redfish/v1/systems/1/Actions/ComputerSystem.Reset", body=body)
+ response = REDFISH_OBJ.post("/redfish/v1/Systems/1/Actions/ComputerSystem.Reset", body=body)
+
+Notes about HTTP methods and arguments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The previous sections showed example GET and POST requests. The following is a list of the different methods supported:
+
+* ``get``: Performs an HTTP GET operation to retrieve a resource from a URI.
+* ``head``: Performs an HTTP HEAD operation to retrieve response headers from a URI, but no body.
+* ``post``: Performs an HTTP POST operation to perform an action or create a new resource.
+* ``put``: Performs an HTTP PUT operation to replace an existing resource.
+* ``patch``: Performs an HTTP PATCH operation to update an existing resource.
+* ``delete``: Performs an HTTP DELETE operation to remove a resource.
+
+Each of the previous methods allows for the following arguments:
+
+* ``path``: **Required**. String. The URI in which to invoke the operation.
+
+ - Example: ``"/redfish/v1/Systems/1"``
+
+* ``args``: Dictionary. Query parameters to supply with the request.
+
+ - The key-value pairs in the dictionary are the query parameter name and the query parameter value to supply.
+ - Example: ``{"$select": "Reading,Status"}``
+
+* ``body``: Dictionary, List, Bytes, or String. The request body to provide with the request.
+
+ - Not supported for ``get``, ``head``, or ``delete`` methods.
+ - The data type supplied will dictate the encoding.
+ - A dictionary is the most common usage, which results in a JSON body.
+ - Example: ``{"ResetType": "GracefulShutdown"}``
+ - A list is used to supply multipart forms, which is useful for multipart HTTP push updates.
+ - Bytes is used to supply an octet stream.
+ - A string is used to supply an unstructed body, which may be used in some OEM cases.
+
+* ``headers``: Dictionary. Additional HTTP headers to supply with the request.
+
+ - The key-value pairs in the dictionary are the HTTP header name and the HTTP header value to supply.
+ - Example: ``{"If-Match": etag_value}``
+
+* ``timeout``: Number. The number of seconds to wait for a response before closing the connection for this request.
+
+ - Overrides the timeout value specified when the Redfish object is created for this request.
+ - This can be useful when a particular URI is known to take a long time to respond, such as with firmware updates.
+ - The default value is ``None``, which indicates the object-defined timeout is used.
+
+* ``max_retry``: Number. The number of retries to perform an operation before giving up for this request.
+
+ - Overrides the max retry value specified when the Redfish object is created for this request.
+ - This can be useful when a particular URI is known to take multiple retries.
+ - The default value is ``None``, which indicates the object-defined max retry count is used.
Working with tasks
~~~~~~~~~~~~~~~~~~
-A POST and PATCH operations may result in a task, describing an operation with a duration greater than the span of a single request.
+POST, PATCH, PUT, and DELETE operations may result in a task, describing an operation with a duration greater than the span of a single request.
The action message object that ``is_processing`` will return a task that can be accessed reviewed when polled with monitor.
An example of a POST operation with a possible task is shown below.
.. code-block:: python
body = {"ResetType": "GracefulShutdown"}
- response = REDFISH_OBJ.post("/redfish/v1/systems/1/Actions/ComputerSystem.Reset", body=body)
+ response = REDFISH_OBJ.post("/redfish/v1/Systems/1/Actions/ComputerSystem.Reset", body=body)
if(response.is_processing):
task = response.monitor(context)
@@ -206,4 +256,4 @@
Copyright Notice:
Copyright 2016-2022 DMTF. All rights reserved.
-License: BSD 3-Clause License. For full text see link: `https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md <https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md>`_
+License: BSD 3-Clause License. For full text see link: `https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md <https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md>`_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/examples/context_manager.py new/python-redfish-library-3.2.1/examples/context_manager.py
--- old/python-redfish-library-3.1.8/examples/context_manager.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/examples/context_manager.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import sys
import redfish
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/examples/discover.py new/python-redfish-library-3.2.1/examples/discover.py
--- old/python-redfish-library-3.1.8/examples/discover.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/examples/discover.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import redfish
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/examples/multipart_push.py new/python-redfish-library-3.2.1/examples/multipart_push.py
--- old/python-redfish-library-3.1.8/examples/multipart_push.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/examples/multipart_push.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import sys
import json
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/examples/quickstart.py new/python-redfish-library-3.2.1/examples/quickstart.py
--- old/python-redfish-library-3.1.8/examples/quickstart.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/examples/quickstart.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import sys
import redfish
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/examples/quickstart_rmc.py new/python-redfish-library-3.2.1/examples/quickstart_rmc.py
--- old/python-redfish-library-3.1.8/examples/quickstart_rmc.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/examples/quickstart_rmc.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import os
import sys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/setup.py new/python-redfish-library-3.2.1/setup.py
--- old/python-redfish-library-3.1.8/setup.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/setup.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
from setuptools import setup, find_packages
from codecs import open
@@ -12,7 +12,7 @@
long_description = f.read()
setup(name='redfish',
- version='3.1.8',
+ version='3.2.1',
description='Redfish Python Library',
long_description=long_description,
long_description_content_type='text/x-rst',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/__init__.py new/python-redfish-library-3.2.1/src/redfish/__init__.py
--- old/python-redfish-library-3.1.8/src/redfish/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,16 +1,17 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
""" Redfish restful library """
-__all__ = ['rest', 'ris', 'discovery']
-__version__ = "3.1.8"
+__all__ = ['rest', 'ris', 'discovery', 'messages']
+__version__ = "3.2.1"
from redfish.rest.v1 import redfish_client
from redfish.rest.v1 import AuthMethod
from redfish.discovery.discovery import discover_ssdp
+from redfish.messages import *
import logging
def redfish_logger(file_name, log_format, log_level=logging.ERROR):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/discovery/__init__.py new/python-redfish-library-3.2.1/src/redfish/discovery/__init__.py
--- old/python-redfish-library-3.1.8/src/redfish/discovery/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/discovery/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,4 +1,4 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/discovery/discovery.py new/python-redfish-library-3.2.1/src/redfish/discovery/discovery.py
--- old/python-redfish-library-3.1.8/src/redfish/discovery/discovery.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/discovery/discovery.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""Discovers Redfish services"""
@@ -82,7 +82,7 @@
"Host: {}:{}\r\n"
'Man: "ssdp:discover"\r\n'
"ST: urn:dmtf-org:service:redfish-rest:1\r\n"
- "MX: {}\r\n"
+ "MX: {}\r\n\r\n"
).format(mcast_ip, port, response_time)
socket.setdefaulttimeout(response_time + 2)
@@ -99,7 +99,7 @@
# On the same socket, wait for responses
discovered_services = {}
pattern = re.compile(
- "^uuid:([a-f0-9\-]*)::urn:dmtf-org:service:redfish-rest:1(:\d)?$") # noqa
+ "^uuid:([a-f0-9\-]*)::urn:dmtf-org:service:redfish-rest:1(:\d+)?$") # noqa
while True:
try:
response = http.client.HTTPResponse(FakeSocket(sock.recv(1024)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/messages/__init__.py new/python-redfish-library-3.2.1/src/redfish/messages/__init__.py
--- old/python-redfish-library-3.1.8/src/redfish/messages/__init__.py 1970-01-01 01:00:00.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/messages/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -0,0 +1,5 @@
+# Copyright Notice:
+# Copyright 2016-2021 DMTF. All rights reserved.
+# License: BSD 3-Clause License. For full text see link:
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
+from .messages import *
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/messages/messages.py new/python-redfish-library-3.2.1/src/redfish/messages/messages.py
--- old/python-redfish-library-3.1.8/src/redfish/messages/messages.py 1970-01-01 01:00:00.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/messages/messages.py 2023-08-04 21:42:35.000000000 +0200
@@ -0,0 +1,148 @@
+#! /usr/bin/python
+# Copyright Notice:
+# Copyright 2019-2020 DMTF. All rights reserved.
+# License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/Redfish-Tacklebox/blob/main/LICENSE.md
+
+"""
+Messages Module
+
+File : messages.py
+
+Brief : This file contains the definitions and functionalities for interacting
+ with Messages for a given Redfish service
+"""
+import re
+
+class RedfishOperationFailedError( Exception ):
+ """
+ Raised when an operation has failed (HTTP Status >= 400)
+ """
+ pass
+
+class RedfishPasswordChangeRequiredError( Exception ):
+ """
+ Raised when password change required
+ """
+ def __str__(self):
+ return "\n{}\nURL: {}\n".format( str(self.args[0]), str(self.args[1]) )
+
+def get_messages_detail( response ):
+ """
+ Builds messages detail dict in the payload
+
+ Args:
+ response: The response to parser
+
+ Returns:
+ The dict containing messages_detail
+ messages_detail["status"]: http status code
+ messages_detail["successful"]: response successful (http status code < 400)
+ messages_detail["code"]: redfish message response code field
+ messages_detail["@Message.ExtendedInfo"]: redfish message response code field
+ """
+
+ messages_detail = {}
+ messages_detail["status"] = response.status
+ messages_detail["text"] = response.text
+ messages_detail["successful"] = False
+ messages_detail["@Message.ExtendedInfo"] = []
+
+ if response.status >= 400:
+ messages_detail["successful"] = False
+ else:
+ messages_detail["successful"] = True
+
+ try:
+ message_body = response.dict
+ messages_detail["body"] = response.dict
+
+ if not "@Message.ExtendedInfo" in message_body:
+ message_body = response.dict["error"]
+ check_message_field = True
+ if "@Message.ExtendedInfo" in message_body:
+ messages_detail["@Message.ExtendedInfo"] = message_body["@Message.ExtendedInfo"]
+ for index in range(len(messages_detail["@Message.ExtendedInfo"])):
+ messages_item = messages_detail["@Message.ExtendedInfo"][index]
+ if not "MessageId" in messages_item:
+ messages_item["MessageId"] = ""
+ if not "Message" in messages_item:
+ messages_item["Message"] = ""
+ messages_detail["@Message.ExtendedInfo"][index] = messages_item
+ check_message_field = False
+
+ if check_message_field is True:
+ messages_detail["@Message.ExtendedInfo"] = []
+ messages_item = {}
+ if "code" in message_body:
+ messages_item["MessageId"] = message_body["code"]
+ else:
+ messages_item["MessageId"] = ""
+ if "message" in message_body:
+ messages_item["Message"] = message_body["message"]
+ else:
+ messages_item["Message"] = ""
+ messages_detail["@Message.ExtendedInfo"].insert(0, messages_item)
+ except:
+ messages_detail["@Message.ExtendedInfo"] = []
+ messages_detail["body"] = {}
+
+ return messages_detail
+
+def search_message(response, message_registry_group, message_registry_id):
+ """
+ search message in the payload
+
+ Args:
+ response: The response to parser
+ message_registry_group: target message_registry_group
+ message_registry_id: target message_registry_id
+ Returns:
+ The dict containing target message detail
+ """
+ if isinstance(response, dict) and "@Message.ExtendedInfo" in response:
+ messages_detail = response
+ else:
+ messages_detail = get_messages_detail(response)
+
+ message_registry_id_search = "^" + message_registry_group + "\.[0-9]+\.[0-9]+\." + message_registry_id +"$"
+
+ for messages_item in messages_detail["@Message.ExtendedInfo"]:
+ if "MessageId" in messages_item:
+ resault = re.search(message_registry_id_search, messages_item["MessageId"])
+ if resault:
+ return messages_item
+ return None
+
+def get_error_messages( response ):
+ """
+ Builds a string based on the error messages in the payload
+
+ Args:
+ response: The response to print
+
+ Returns:
+ The string containing error messages
+ """
+
+ # Pull out the error payload and the messages
+
+ out_string = ""
+ try:
+ if isinstance(response, dict) and "@Message.ExtendedInfo" in response:
+ messages_detail = response
+ else:
+ messages_detail = get_messages_detail(response)
+
+ if "@Message.ExtendedInfo" in messages_detail:
+ for message in messages_detail["@Message.ExtendedInfo"]:
+ if "Message" in message:
+ out_string = out_string + "\n" + message["Message"]
+ else:
+ out_string = out_string + "\n" + message["MessageId"]
+ out_string = out_string + "\n"
+ except:
+ # No response body
+ out_string = ""
+
+ return out_string
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/rest/__init__.py new/python-redfish-library-3.2.1/src/redfish/rest/__init__.py
--- old/python-redfish-library-3.1.8/src/redfish/rest/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/rest/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,6 +1,6 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
""" Utilities to simplify interaction with Redfish data """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/rest/v1.py new/python-redfish-library-3.2.1/src/redfish/rest/v1.py
--- old/python-redfish-library-3.1.8/src/redfish/rest/v1.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/rest/v1.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""Helper module for working with REST technology."""
@@ -18,6 +18,7 @@
import re
import requests
import requests_unixsocket
+from redfish.messages import *
from collections import (OrderedDict)
@@ -52,7 +53,9 @@
class ServerDownOrUnreachableError(Exception):
"""Raised when server is unreachable."""
- pass
+ def __init__(self,message,*,response=None):
+ super().__init__(message)
+ self.response = response
class DecompressResponseError(Exception):
"""Raised when decompressing response failed."""
@@ -590,7 +593,7 @@
if resp.status != 200:
raise ServerDownOrUnreachableError("Server not reachable, " \
- "return code: %d" % resp.status)
+ "return code: %d" % resp.status,response=resp)
content = resp.text
@@ -605,106 +608,130 @@
self.root = RisObject.parse(root_data)
self.root_resp = resp
- def get(self, path, args=None, headers=None):
+ def get(self, path, args=None, headers=None, timeout=None, max_retry=None):
"""Perform a GET request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to get.
- :type args: dict.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Get'
"""
try:
return self._rest_request(path, method='GET', args=args,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
except ValueError:
str = "Service responded with invalid JSON at URI {}".format(path)
LOGGER.error(str)
raise JsonDecodingError(str) from None
- def head(self, path, args=None, headers=None):
+ def head(self, path, args=None, headers=None, timeout=None, max_retry=None):
"""Perform a HEAD request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to get.
- :type args: dict.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Head'
"""
return self._rest_request(path, method='HEAD', args=args,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
- def post(self, path, args=None, body=None, headers=None):
+ def post(self, path, args=None, body=None, headers=None, timeout=None, max_retry=None):
"""Perform a POST request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to post.
- :type args: dict.
- :param body: the body to the sent.
- :type body: str.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param body: The request body to provide; use a dict for a JSON body, list for multipart forms, bytes for an octet stream, or str for an unstructured request
+ :type body: dict or list or bytes or str, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Post'
"""
return self._rest_request(path, method='POST', args=args, body=body,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
- def put(self, path, args=None, body=None, headers=None):
+ def put(self, path, args=None, body=None, headers=None, timeout=None, max_retry=None):
"""Perform a PUT request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to put.
- :type args: dict.
- :param body: the body to the sent.
- :type body: str.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param body: The request body to provide; use a dict for a JSON body, list for multipart forms, bytes for an octet stream, or str for an unstructured request
+ :type body: dict or list or bytes or str, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Put'
"""
return self._rest_request(path, method='PUT', args=args, body=body,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
- def patch(self, path, args=None, body=None, headers=None):
- """Perform a PUT request
+ def patch(self, path, args=None, body=None, headers=None, timeout=None, max_retry=None):
+ """Perform a PATCH request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to patch.
- :type args: dict.
- :param body: the body to the sent.
- :type body: str.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param body: The request body to provide; use a dict for a JSON body, list for multipart forms, bytes for an octet stream, or str for an unstructured request
+ :type body: dict or list or bytes or str, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Patch'
"""
return self._rest_request(path, method='PATCH', args=args, body=body,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
- def delete(self, path, args=None, headers=None):
+ def delete(self, path, args=None, headers=None, timeout=None, max_retry=None):
"""Perform a DELETE request
- :param path: the URL path.
- :type path: str.
- :param args: the arguments to delete.
- :type args: dict.
- :param headers: dict of headers to be appended.
- :type headers: dict.
+ :param path: The URI to access
+ :type path: str
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a rest request with method 'Delete'
"""
return self._rest_request(path, method='DELETE', args=args,
- headers=headers)
+ headers=headers, timeout=timeout, max_retry=max_retry)
def _get_req_headers(self, headers=None):
"""Get the request headers
@@ -728,24 +755,34 @@
return headers
def _rest_request(self, path, method='GET', args=None, body=None,
- headers=None, allow_redirects=True):
+ headers=None, allow_redirects=True, timeout=None, max_retry=None):
"""Rest request main function
- :param path: path within tree
+ :param path: The URI to access
:type path: str
- :param method: method to be implemented
- :type method: str
- :param args: the arguments for method
- :type args: dict
- :param body: body payload for the rest call
- :type body: dict
- :param headers: provide additional headers
- :type headers: dict
- :param allow_redirects: controls whether redirects are followed
- :type allow_redirects: bool
+ :param method: The HTTP method to invoke on the URI; GET if not provided
+ :type method: str, optional
+ :param args: The query parameters to provide with the request
+ :type args: dict, optional
+ :param body: The request body to provide; use a dict for a JSON body, list for multipart forms, bytes for an octet stream, or str for an unstructured request
+ :type body: dict or list or bytes or str, optional
+ :param headers: Additional HTTP headers to provide in the request
+ :type headers: dict, optional
+ :param allow_redirects: Controls whether redirects are followed
+ :type allow_redirects: bool, optional
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int, optional
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int, optional
:returns: returns a RestResponse object
"""
+ if timeout is None:
+ timeout = self._timeout
+
+ if max_retry is None:
+ max_retry = self._max_retry
+
headers = self._get_req_headers(headers)
reqpath = path.replace('//', '/')
@@ -784,7 +821,7 @@
body = urlencode(body)
if method == 'PUT':
- resp = self._rest_request(path=path)
+ resp = self._rest_request(path=path, timeout=timeout, max_retry=max_retry)
try:
if resp.getheader('content-encoding') == 'gzip':
@@ -834,7 +871,7 @@
attempts = 0
restresp = None
cause_exception = None
- while attempts <= self._max_retry:
+ while attempts <= max_retry:
if LOGGER.isEnabledFor(logging.DEBUG):
headerstr = ''
if headers is not None:
@@ -871,7 +908,7 @@
if self.cafile:
verify = self.cafile
resp = self._session.request(method.upper(), "{}{}".format(self.__base_url, reqpath), data=body,
- headers=headers, timeout=self._timeout, allow_redirects=allow_redirects,
+ headers=headers, timeout=timeout, allow_redirects=allow_redirects,
verify=verify, proxies=self._proxies, params=query_str)
if sys.version_info < (3, 3):
@@ -959,6 +996,10 @@
self.__session_key = resp.session_key
self.__session_location = resp.session_location
+ message_item = search_message(resp, "Base", "PasswordChangeRequired")
+ if not message_item is None:
+ raise RedfishPasswordChangeRequiredError("Password Change Required\n", message_item["MessageArgs"][0])
+
if not self.__session_key and resp.status not in [200, 201, 202, 204]:
if resp.status == 401:
# Invalid credentials supplied
@@ -1044,7 +1085,7 @@
self.login_url = '/redfish/v1/SessionService/Sessions'
def _rest_request(self, path='', method="GET", args=None, body=None,
- headers=None, allow_redirects=True):
+ headers=None, allow_redirects=True, timeout=None, max_retry=None):
"""Rest request for HTTP client
:param path: path within tree
@@ -1059,13 +1100,17 @@
:type headers: dict
:param allow_redirects: controls whether redirects are followed
:type allow_redirects: bool
+ :param timeout: Timeout in seconds for the initial connection for this specific request
+ :type timeout: int
+ :param max_retry: Number of times a request will retry after a timeout for this specific request
+ :type max_retry: int
:returns: returns a rest request
"""
return super(HttpClient, self)._rest_request(path=path, method=method,
args=args, body=body,
headers=headers,
- allow_redirects=allow_redirects)
+ allow_redirects=allow_redirects, timeout=timeout, max_retry=max_retry)
def _get_req_headers(self, headers=None, providerheader=None):
"""Get the request headers for HTTP client
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/__init__.py new/python-redfish-library-3.2.1/src/redfish/ris/__init__.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/config.py new/python-redfish-library-3.2.1/src/redfish/ris/config.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/config.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/config.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""Module for working with global configuration options."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/ris.py new/python-redfish-library-3.2.1/src/redfish/ris/ris.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/ris.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/ris.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""RIS implementation"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/rmc.py new/python-redfish-library-3.2.1/src/redfish/ris/rmc.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/rmc.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/rmc.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""RMC implementation """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/rmc_helper.py new/python-redfish-library-3.2.1/src/redfish/ris/rmc_helper.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/rmc_helper.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/rmc_helper.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
"""RMC helper implementation"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/src/redfish/ris/sharedtypes.py new/python-redfish-library-3.2.1/src/redfish/ris/sharedtypes.py
--- old/python-redfish-library-3.1.8/src/redfish/ris/sharedtypes.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/src/redfish/ris/sharedtypes.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- coding: utf-8 -*-
""" Shared types used in this module """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/__init__.py new/python-redfish-library-3.2.1/tests/__init__.py
--- old/python-redfish-library-3.1.8/tests/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,4 +1,4 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
\ No newline at end of file
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/discovery/__init__.py new/python-redfish-library-3.2.1/tests/discovery/__init__.py
--- old/python-redfish-library-3.1.8/tests/discovery/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/discovery/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,4 +1,4 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
\ No newline at end of file
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/discovery/test_discovery.py new/python-redfish-library-3.2.1/tests/discovery/test_discovery.py
--- old/python-redfish-library-3.1.8/tests/discovery/test_discovery.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/discovery/test_discovery.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- encoding: utf-8 -*-
import unittest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/rest/__init__.py new/python-redfish-library-3.2.1/tests/rest/__init__.py
--- old/python-redfish-library-3.1.8/tests/rest/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/rest/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,4 +1,4 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
\ No newline at end of file
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/rest/test_v1.py new/python-redfish-library-3.2.1/tests/rest/test_v1.py
--- old/python-redfish-library-3.1.8/tests/rest/test_v1.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/rest/test_v1.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- encoding: utf-8 -*-
import unittest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/ris/__init__.py new/python-redfish-library-3.2.1/tests/ris/__init__.py
--- old/python-redfish-library-3.1.8/tests/ris/__init__.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/ris/__init__.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,4 +1,4 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
\ No newline at end of file
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/ris/test_config.py new/python-redfish-library-3.2.1/tests/ris/test_config.py
--- old/python-redfish-library-3.1.8/tests/ris/test_config.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/ris/test_config.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- encoding: utf-8 -*-
import tempfile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/ris/test_ris.py new/python-redfish-library-3.2.1/tests/ris/test_ris.py
--- old/python-redfish-library-3.1.8/tests/ris/test_ris.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/ris/test_ris.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
# -*- encoding: utf-8 -*-
import unittest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-redfish-library-3.1.8/tests/ris/test_rmc_helper.py new/python-redfish-library-3.2.1/tests/ris/test_rmc_helper.py
--- old/python-redfish-library-3.1.8/tests/ris/test_rmc_helper.py 2022-12-02 21:21:09.000000000 +0100
+++ new/python-redfish-library-3.2.1/tests/ris/test_rmc_helper.py 2023-08-04 21:42:35.000000000 +0200
@@ -1,7 +1,7 @@
# Copyright Notice:
# Copyright 2016-2021 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
-# https://github.com/DMTF/python-redfish-library/blob/master/LICENSE.md
+# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md
import unittest
try:
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-simpleeval for openSUSE:Factory checked in at 2024-01-03 12:23:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-simpleeval (Old)
and /work/SRC/openSUSE:Factory/.python-simpleeval.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-simpleeval"
Wed Jan 3 12:23:57 2024 rev:6 rq:1135607 version:0.9.13
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-simpleeval/python-simpleeval.changes 2022-02-23 16:27:09.659510357 +0100
+++ /work/SRC/openSUSE:Factory/.python-simpleeval.new.28375/python-simpleeval.changes 2024-01-03 12:23:57.721228048 +0100
@@ -1,0 +2,12 @@
+Fri Dec 29 09:15:41 UTC 2023 - Dirk Müller <dmueller(a)suse.com>
+
+- update to 0.9.13:
+ * Better handling of empty strings passed as input.
+ * Fix the shift safe number issue from 0.9.12
+ * More minor pylint / etc fixes / cleanups (general code
+ quality)
+ * separate `.parse` from #115
+ * Allow setting up completely empty `{}` operators / functions
+ * Add extra bit-ops from #87
+
+-------------------------------------------------------------------
Old:
----
simpleeval-0.9.12.tar.gz
New:
----
simpleeval-0.9.13.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-simpleeval.spec ++++++
--- /var/tmp/diff_new_pack.j1dpzp/_old 2024-01-03 12:23:58.365251579 +0100
+++ /var/tmp/diff_new_pack.j1dpzp/_new 2024-01-03 12:23:58.365251579 +0100
@@ -1,7 +1,7 @@
#
# spec file
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
# Copyright (c) 2015 Dr. Axel Braun
#
# All modifications and additions to the file contributed by third parties
@@ -20,7 +20,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define modname simpleeval
Name: python-%{modname}
-Version: 0.9.12
+Version: 0.9.13
Release: 0
Summary: A simple, safe single expression evaluator library
License: MIT
++++++ simpleeval-0.9.12.tar.gz -> simpleeval-0.9.13.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/Makefile new/simpleeval-0.9.13/Makefile
--- old/simpleeval-0.9.12/Makefile 2022-01-15 17:00:46.000000000 +0100
+++ new/simpleeval-0.9.13/Makefile 2023-02-17 09:21:11.000000000 +0100
@@ -24,6 +24,8 @@
lint:
black --check --diff simpleeval.py test_simpleeval.py
isort --check-only --diff simpleeval.py test_simpleeval.py
+ pylint simpleeval.py test_simpleeval.py
+ mypy simpleeval.py test_simpleeval.py
format:
black simpleeval.py test_simpleeval.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/PKG-INFO new/simpleeval-0.9.13/PKG-INFO
--- old/simpleeval-0.9.12/PKG-INFO 2022-01-15 18:31:14.599136400 +0100
+++ new/simpleeval-0.9.13/PKG-INFO 2023-02-17 09:24:18.891371300 +0100
@@ -1,13 +1,11 @@
Metadata-Version: 2.1
Name: simpleeval
-Version: 0.9.12
+Version: 0.9.13
Summary: A simple, safe single expression evaluator library.
Home-page: https://github.com/danthedeckie/simpleeval
Author: Daniel Fairhead
Author-email: danthedeckie(a)gmail.com
-License: UNKNOWN
Keywords: eval,simple,expression,parse,ast
-Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
@@ -31,7 +29,14 @@
:target: https://badge.fury.io/py/simpleeval
:alt: PyPI Version
-A quick single file library for easily adding evaluatable expressions into
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+
+.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
+ :target: https://github.com/PyCQA/pylint
+
+
+A single file library for easily adding evaluatable expressions into
python projects. Say you want to allow a user to set an alarm volume, which
could depend on the time of day, alarm level, how many previous alarms had gone
off, and if there is music playing at the time.
@@ -39,8 +44,9 @@
Or if you want to allow simple formulae in a web application, but don't want to
give full eval() access, or don't want to run in javascript on the client side.
-It's deliberately very simple, pull it in from PyPI (pip or easy_install), or
-even just a single file you can dump into a project.
+It's deliberately trying to stay simple to use and not have millions of features,
+pull it in from PyPI (pip or easy_install), or even just a single file you can dump
+into a project.
Internally, it's using the amazing python ``ast`` module to parse the
expression, which allows very fine control of what is and isn't allowed. It
@@ -55,7 +61,7 @@
You should be aware of this when deploying in a public setting.
-The defaults are pretty locked down and basic, and it's very easy to add
+The defaults are pretty locked down and basic, and it's easy to add
whatever extra specific functionality you need (your own functions,
variable/name lookup, etc).
@@ -149,23 +155,36 @@
| | ``"spam" in "my breakfast"`` |
| | -> ``False`` |
+--------+------------------------------------+
+| ``^`` | "bitwise exclusive OR" (xor) |
+| | ``62 ^ 20`` -> ``42`` |
++--------+------------------------------------+
+| ``|`` | "bitwise OR" |
+| | ``8 | 34`` -> ``42`` |
++--------+------------------------------------+
+| ``&`` | "bitwise AND" |
+| | ``100 & 63`` -> ``36`` |
++--------+------------------------------------+
+| ``~`` | "bitwise invert" |
+| | ``~ -43`` -> ``42`` |
++--------+------------------------------------+
-The ``^`` operator is notably missing - not because it's hard, but because it
-is often mistaken for a exponent operator, not the bitwise operation that it is
-in python. It's trivial to add back in again if you wish (using the class
-based evaluator explained below):
+The ``^`` operator is often mistaken for a exponent operator, not the bitwise
+operation that it is in python, so if you want ``3 ^ 2`` to equal ``9``, you can
+replace the operator like this:
.. code-block:: python
>>> import ast
- >>> import operator
+ >>> from simpleeval import safe_power
>>> s = SimpleEval()
- >>> s.operators[ast.BitXor] = operator.xor
+ >>> s.operators[ast.BitXor] = safe_power
+
+ >>> s.eval("3 ^ 2")
+ 9
- >>> s.eval("2 ^ 10")
- 8
+for example.
Limited Power
~~~~~~~~~~~~~
@@ -305,6 +324,22 @@
# and so on...
+One useful feature of using the ``SimpleEval`` object is that you can parse an expression
+once, and then evaluate it mulitple times using different ``names``:
+
+.. code-block:: python
+
+ # Set up & Cache the parse tree:
+ expression = "foo + bar"
+ parsed = s.parse(expression)
+
+ # evaluate the expression multiple times:
+ for names in [{"foo": 1, "bar": 10}, {"foo": 100, "bar": 42}]:
+ s.names = names
+ print(s.eval(expression, previously_parsed=parsed))
+
+for instance. This may help with performance.
+
You can assign / edit the various options of the ``SimpleEval`` object if you
want to. Either assign them during creation (like the ``simple_eval``
function)
@@ -418,11 +453,18 @@
(requires ``entr``)
+I'm trying to keep the codebase relatively clean with Black, isort, pylint & mypy.
+See::
+
+ $ make format
+
+and::
+
+ $ make lint
+
BEWARE
------
-I've done the best I can with this library - but there's no warrenty, no guarentee, nada. A lot of
+I've done the best I can with this library - but there's no warranty, no guarantee, nada. A lot of
very clever people think the whole idea of trying to sandbox CPython is impossible. Read the code
yourself, and use it at your own risk.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/README.rst new/simpleeval-0.9.13/README.rst
--- old/simpleeval-0.9.12/README.rst 2022-01-15 16:40:37.000000000 +0100
+++ new/simpleeval-0.9.13/README.rst 2023-02-17 09:23:37.000000000 +0100
@@ -13,7 +13,14 @@
:target: https://badge.fury.io/py/simpleeval
:alt: PyPI Version
-A quick single file library for easily adding evaluatable expressions into
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+
+.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
+ :target: https://github.com/PyCQA/pylint
+
+
+A single file library for easily adding evaluatable expressions into
python projects. Say you want to allow a user to set an alarm volume, which
could depend on the time of day, alarm level, how many previous alarms had gone
off, and if there is music playing at the time.
@@ -21,8 +28,9 @@
Or if you want to allow simple formulae in a web application, but don't want to
give full eval() access, or don't want to run in javascript on the client side.
-It's deliberately very simple, pull it in from PyPI (pip or easy_install), or
-even just a single file you can dump into a project.
+It's deliberately trying to stay simple to use and not have millions of features,
+pull it in from PyPI (pip or easy_install), or even just a single file you can dump
+into a project.
Internally, it's using the amazing python ``ast`` module to parse the
expression, which allows very fine control of what is and isn't allowed. It
@@ -37,7 +45,7 @@
You should be aware of this when deploying in a public setting.
-The defaults are pretty locked down and basic, and it's very easy to add
+The defaults are pretty locked down and basic, and it's easy to add
whatever extra specific functionality you need (your own functions,
variable/name lookup, etc).
@@ -131,23 +139,36 @@
| | ``"spam" in "my breakfast"`` |
| | -> ``False`` |
+--------+------------------------------------+
+| ``^`` | "bitwise exclusive OR" (xor) |
+| | ``62 ^ 20`` -> ``42`` |
++--------+------------------------------------+
+| ``|`` | "bitwise OR" |
+| | ``8 | 34`` -> ``42`` |
++--------+------------------------------------+
+| ``&`` | "bitwise AND" |
+| | ``100 & 63`` -> ``36`` |
++--------+------------------------------------+
+| ``~`` | "bitwise invert" |
+| | ``~ -43`` -> ``42`` |
++--------+------------------------------------+
-The ``^`` operator is notably missing - not because it's hard, but because it
-is often mistaken for a exponent operator, not the bitwise operation that it is
-in python. It's trivial to add back in again if you wish (using the class
-based evaluator explained below):
+The ``^`` operator is often mistaken for a exponent operator, not the bitwise
+operation that it is in python, so if you want ``3 ^ 2`` to equal ``9``, you can
+replace the operator like this:
.. code-block:: python
>>> import ast
- >>> import operator
+ >>> from simpleeval import safe_power
>>> s = SimpleEval()
- >>> s.operators[ast.BitXor] = operator.xor
+ >>> s.operators[ast.BitXor] = safe_power
- >>> s.eval("2 ^ 10")
- 8
+ >>> s.eval("3 ^ 2")
+ 9
+
+for example.
Limited Power
~~~~~~~~~~~~~
@@ -287,6 +308,22 @@
# and so on...
+One useful feature of using the ``SimpleEval`` object is that you can parse an expression
+once, and then evaluate it mulitple times using different ``names``:
+
+.. code-block:: python
+
+ # Set up & Cache the parse tree:
+ expression = "foo + bar"
+ parsed = s.parse(expression)
+
+ # evaluate the expression multiple times:
+ for names in [{"foo": 1, "bar": 10}, {"foo": 100, "bar": 42}]:
+ s.names = names
+ print(s.eval(expression, previously_parsed=parsed))
+
+for instance. This may help with performance.
+
You can assign / edit the various options of the ``SimpleEval`` object if you
want to. Either assign them during creation (like the ``simple_eval``
function)
@@ -400,9 +437,18 @@
(requires ``entr``)
+I'm trying to keep the codebase relatively clean with Black, isort, pylint & mypy.
+See::
+
+ $ make format
+
+and::
+
+ $ make lint
+
BEWARE
------
-I've done the best I can with this library - but there's no warrenty, no guarentee, nada. A lot of
+I've done the best I can with this library - but there's no warranty, no guarantee, nada. A lot of
very clever people think the whole idea of trying to sandbox CPython is impossible. Read the code
yourself, and use it at your own risk.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/pyproject.toml new/simpleeval-0.9.13/pyproject.toml
--- old/simpleeval-0.9.12/pyproject.toml 2022-01-15 17:27:18.000000000 +0100
+++ new/simpleeval-0.9.13/pyproject.toml 2023-02-17 09:21:11.000000000 +0100
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools>=30.3.0", "wheel", "build"]
+requires = ["setuptools>=30.3.0", "wheel"]
build-backend = "setuptools.build_meta"
[tool.black]
@@ -16,7 +16,9 @@
[tool.pylint.messages_control]
disable = [
+ "fixme",
"consider-using-f-string",
+ "raise-missing-from",
"invalid-name",
"too-few-public-methods",
"too-many-public-methods",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/setup.cfg new/simpleeval-0.9.13/setup.cfg
--- old/simpleeval-0.9.12/setup.cfg 2022-01-15 18:31:14.599745300 +0100
+++ new/simpleeval-0.9.13/setup.cfg 2023-02-17 09:24:18.892493500 +0100
@@ -1,6 +1,6 @@
[metadata]
name = simpleeval
-version = 0.9.12
+version = 0.9.13
author = Daniel Fairhead
author_email = danthedeckie(a)gmail.com
description = A simple, safe single expression evaluator library.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/simpleeval.egg-info/PKG-INFO new/simpleeval-0.9.13/simpleeval.egg-info/PKG-INFO
--- old/simpleeval-0.9.12/simpleeval.egg-info/PKG-INFO 2022-01-15 18:31:14.000000000 +0100
+++ new/simpleeval-0.9.13/simpleeval.egg-info/PKG-INFO 2023-02-17 09:24:18.000000000 +0100
@@ -1,13 +1,11 @@
Metadata-Version: 2.1
Name: simpleeval
-Version: 0.9.12
+Version: 0.9.13
Summary: A simple, safe single expression evaluator library.
Home-page: https://github.com/danthedeckie/simpleeval
Author: Daniel Fairhead
Author-email: danthedeckie(a)gmail.com
-License: UNKNOWN
Keywords: eval,simple,expression,parse,ast
-Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
@@ -31,7 +29,14 @@
:target: https://badge.fury.io/py/simpleeval
:alt: PyPI Version
-A quick single file library for easily adding evaluatable expressions into
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+
+.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
+ :target: https://github.com/PyCQA/pylint
+
+
+A single file library for easily adding evaluatable expressions into
python projects. Say you want to allow a user to set an alarm volume, which
could depend on the time of day, alarm level, how many previous alarms had gone
off, and if there is music playing at the time.
@@ -39,8 +44,9 @@
Or if you want to allow simple formulae in a web application, but don't want to
give full eval() access, or don't want to run in javascript on the client side.
-It's deliberately very simple, pull it in from PyPI (pip or easy_install), or
-even just a single file you can dump into a project.
+It's deliberately trying to stay simple to use and not have millions of features,
+pull it in from PyPI (pip or easy_install), or even just a single file you can dump
+into a project.
Internally, it's using the amazing python ``ast`` module to parse the
expression, which allows very fine control of what is and isn't allowed. It
@@ -55,7 +61,7 @@
You should be aware of this when deploying in a public setting.
-The defaults are pretty locked down and basic, and it's very easy to add
+The defaults are pretty locked down and basic, and it's easy to add
whatever extra specific functionality you need (your own functions,
variable/name lookup, etc).
@@ -149,23 +155,36 @@
| | ``"spam" in "my breakfast"`` |
| | -> ``False`` |
+--------+------------------------------------+
+| ``^`` | "bitwise exclusive OR" (xor) |
+| | ``62 ^ 20`` -> ``42`` |
++--------+------------------------------------+
+| ``|`` | "bitwise OR" |
+| | ``8 | 34`` -> ``42`` |
++--------+------------------------------------+
+| ``&`` | "bitwise AND" |
+| | ``100 & 63`` -> ``36`` |
++--------+------------------------------------+
+| ``~`` | "bitwise invert" |
+| | ``~ -43`` -> ``42`` |
++--------+------------------------------------+
-The ``^`` operator is notably missing - not because it's hard, but because it
-is often mistaken for a exponent operator, not the bitwise operation that it is
-in python. It's trivial to add back in again if you wish (using the class
-based evaluator explained below):
+The ``^`` operator is often mistaken for a exponent operator, not the bitwise
+operation that it is in python, so if you want ``3 ^ 2`` to equal ``9``, you can
+replace the operator like this:
.. code-block:: python
>>> import ast
- >>> import operator
+ >>> from simpleeval import safe_power
>>> s = SimpleEval()
- >>> s.operators[ast.BitXor] = operator.xor
+ >>> s.operators[ast.BitXor] = safe_power
+
+ >>> s.eval("3 ^ 2")
+ 9
- >>> s.eval("2 ^ 10")
- 8
+for example.
Limited Power
~~~~~~~~~~~~~
@@ -305,6 +324,22 @@
# and so on...
+One useful feature of using the ``SimpleEval`` object is that you can parse an expression
+once, and then evaluate it mulitple times using different ``names``:
+
+.. code-block:: python
+
+ # Set up & Cache the parse tree:
+ expression = "foo + bar"
+ parsed = s.parse(expression)
+
+ # evaluate the expression multiple times:
+ for names in [{"foo": 1, "bar": 10}, {"foo": 100, "bar": 42}]:
+ s.names = names
+ print(s.eval(expression, previously_parsed=parsed))
+
+for instance. This may help with performance.
+
You can assign / edit the various options of the ``SimpleEval`` object if you
want to. Either assign them during creation (like the ``simple_eval``
function)
@@ -418,11 +453,18 @@
(requires ``entr``)
+I'm trying to keep the codebase relatively clean with Black, isort, pylint & mypy.
+See::
+
+ $ make format
+
+and::
+
+ $ make lint
+
BEWARE
------
-I've done the best I can with this library - but there's no warrenty, no guarentee, nada. A lot of
+I've done the best I can with this library - but there's no warranty, no guarantee, nada. A lot of
very clever people think the whole idea of trying to sandbox CPython is impossible. Read the code
yourself, and use it at your own risk.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/simpleeval.py new/simpleeval-0.9.13/simpleeval.py
--- old/simpleeval-0.9.12/simpleeval.py 2022-01-15 18:18:56.000000000 +0100
+++ new/simpleeval-0.9.13/simpleeval.py 2023-02-17 09:21:11.000000000 +0100
@@ -1,5 +1,5 @@
"""
-SimpleEval - (C) 2013-2022 Daniel Fairhead
+SimpleEval - (C) 2013-2023 Daniel Fairhead
-------------------------------------
An short, easy to use, safe and reasonably extensible expression evaluator.
@@ -49,12 +49,14 @@
- mommothazaz123 (Andrew Zhu) f"string" support, Python 3.8 support
- lubieowoce (Uryga) various potential vulnerabilities
- JCavallo (Jean Cavallo) names dict shouldn't be modified
-- Birne94 (Daniel Birnstiel) for fixing leaking generators.
+- Birne94 (Daniel Birnstiel) for fixing leaking generators, star expressions
- patricksurry (Patrick Surry) or should return last value, even if falsy.
- shughes-uk (Samantha Hughes) python w/o 'site' should not fail to import.
-- KOLANICH packaging / deployment / setup help & << + >> ops
+- KOLANICH packaging / deployment / setup help & << + >> & other bit ops
- graingert (Thomas Grainger) packaging / deployment / setup help
- bozokopic (Bozo Kopic) Memory leak fix
+- daxamin (Dax Amin) Better error for attempting to eval empty string
+- smurfix (Matthias Urlichs) Allow clearing functions / operators / etc completely
-------------------------------------
Basic Usage:
@@ -101,6 +103,7 @@
from random import random
PYTHON3 = sys.version_info[0] == 3
+PYTHON35 = PYTHON3 and sys.version_info > (3, 5)
########################################
# Module wide 'globals'
@@ -109,6 +112,7 @@
MAX_COMPREHENSION_LENGTH = 10000
MAX_POWER = 4000000 # highest exponent
MAX_SHIFT = 10000 # highest << or >> (lshift / rshift)
+MAX_SHIFT_BASE = int(sys.float_info.max) # highest on left side of << or >>
DISALLOW_PREFIXES = ["_", "func_"]
DISALLOW_METHODS = ["format", "format_map", "mro"]
@@ -121,7 +125,7 @@
# builtins is a dict in python >3.6 but a module before
DISALLOW_FUNCTIONS = {type, isinstance, eval, getattr, setattr, repr, compile, open}
if hasattr(__builtins__, "help") or (
- hasattr(__builtins__, "__contains__") and "help" in __builtins__
+ hasattr(__builtins__, "__contains__") and "help" in __builtins__ # type: ignore
):
# PyInstaller environment doesn't include this module.
DISALLOW_FUNCTIONS.add(help)
@@ -179,6 +183,17 @@
super(InvalidExpression, self).__init__(self.message)
+class OperatorNotDefined(InvalidExpression):
+ """operator does not exist"""
+
+ def __init__(self, attr, expression):
+ self.message = "Operator '{0}' does not exist in expression '{1}'".format(attr, expression)
+ self.attr = attr
+ self.expression = expression
+
+ super(InvalidExpression, self).__init__(self.message)
+
+
class FeatureNotAvailable(InvalidExpression):
"""What you're trying to do is not allowed."""
@@ -204,6 +219,12 @@
pass
+class MultipleExpressions(UserWarning):
+ """Only the first expression parsed will be used"""
+
+ pass
+
+
########################################
# Default simple functions to include:
@@ -219,7 +240,7 @@
if abs(a) > MAX_POWER or abs(b) > MAX_POWER:
raise NumberTooHigh("Sorry! I don't want to evaluate {0} ** {1}".format(a, b))
- return a ** b
+ return a**b
def safe_mult(a, b): # pylint: disable=invalid-name
@@ -245,15 +266,15 @@
def safe_rshift(a, b): # pylint: disable=invalid-name
- """rshift, but with the maximum"""
- if abs(b) > MAX_SHIFT:
+ """rshift, but with input limits"""
+ if abs(b) > MAX_SHIFT or abs(a) > MAX_SHIFT_BASE:
raise NumberTooHigh("Sorry! I don't want to evaluate {0} >> {1}".format(a, b))
return a >> b
def safe_lshift(a, b): # pylint: disable=invalid-name
- """lshift, but with the maximum"""
- if abs(b) > MAX_SHIFT:
+ """lshift, but with input limits"""
+ if abs(b) > MAX_SHIFT or abs(a) > MAX_SHIFT_BASE:
raise NumberTooHigh("Sorry! I don't want to evaluate {0} << {1}".format(a, b))
return a << b
@@ -280,6 +301,10 @@
ast.Not: op.not_,
ast.USub: op.neg,
ast.UAdd: op.pos,
+ ast.BitXor: op.xor,
+ ast.BitOr: op.or_,
+ ast.BitAnd: op.and_,
+ ast.Invert: op.invert,
ast.In: lambda x, y: op.contains(y, x),
ast.NotIn: lambda x, y: not op.contains(y, x),
ast.Is: lambda x, y: x is y,
@@ -291,7 +316,8 @@
"randint": random_int,
"int": int,
"float": float,
- "str": str if PYTHON3 else unicode,
+ # pylint: disable=undefined-variable
+ "str": str if PYTHON3 else unicode, # type: ignore
}
DEFAULT_NAMES = {"True": True, "False": False, "None": None}
@@ -317,11 +343,11 @@
Create the evaluator instance. Set up valid operators (+,-, etc)
functions (add, random, get_val, whatever) and names."""
- if not operators:
+ if operators is None:
operators = DEFAULT_OPERATORS.copy()
- if not functions:
+ if functions is None:
functions = DEFAULT_FUNCTIONS.copy()
- if not names:
+ if names is None:
names = DEFAULT_NAMES.copy()
self.operators = operators
@@ -377,16 +403,29 @@
def __del__(self):
self.nodes = None
- def eval(self, expr):
+ @staticmethod
+ def parse(expr):
+ """parse an expression into a node tree"""
+
+ parsed = ast.parse(expr.strip())
+
+ if not parsed.body:
+ raise InvalidExpression("Sorry, cannot evaluate empty string")
+ if len(parsed.body) > 1:
+ warnings.warn(
+ "'{}' contains multiple expressions. Only the first will be used.".format(expr),
+ MultipleExpressions,
+ )
+ return parsed.body[0]
+
+ def eval(self, expr, previously_parsed=None):
"""evaluate an expresssion, using the operators, functions and
names previously set up."""
# set a copy of the expression aside, so we can give nice errors...
-
self.expr = expr
- # and evaluate:
- return self._eval(ast.parse(expr.strip()).body[0])
+ return self._eval(previously_parsed or self.parse(expr))
def _eval(self, node):
"""The internal evaluator used on each node in the parsed tree."""
@@ -415,7 +454,8 @@
)
return self._eval(node.value)
- def _eval_import(self, node):
+ @staticmethod
+ def _eval_import(node):
raise FeatureNotAvailable("Sorry, 'import' is not allowed.")
@staticmethod
@@ -441,25 +481,32 @@
return node.value
def _eval_unaryop(self, node):
- return self.operators[type(node.op)](self._eval(node.operand))
+ try:
+ operator = self.operators[type(node.op)]
+ except KeyError:
+ raise OperatorNotDefined(node.op, self.expr)
+ return operator(self._eval(node.operand))
def _eval_binop(self, node):
- return self.operators[type(node.op)](self._eval(node.left), self._eval(node.right))
+ try:
+ operator = self.operators[type(node.op)]
+ except KeyError:
+ raise OperatorNotDefined(node.op, self.expr)
+ return operator(self._eval(node.left), self._eval(node.right))
def _eval_boolop(self, node):
+ to_return = False
if isinstance(node.op, ast.And):
- vout = False
for value in node.values:
- vout = self._eval(value)
- if not vout:
- return vout
- return vout
+ to_return = self._eval(value)
+ if not to_return:
+ break
elif isinstance(node.op, ast.Or):
for value in node.values:
- vout = self._eval(value)
- if vout:
- return vout
- return vout
+ to_return = self._eval(value)
+ if to_return:
+ break
+ return to_return
def _eval_compare(self, node):
right = self._eval(node.left)
@@ -483,7 +530,7 @@
func = self.functions[node.func.id]
except KeyError:
raise FunctionNotDefined(node.func.id, self.expr)
- except AttributeError as e:
+ except AttributeError:
raise FeatureNotAvailable("Lambda Functions not implemented")
if func in DISALLOW_FUNCTIONS:
@@ -505,14 +552,13 @@
# pass that to ast.parse)
if hasattr(self.names, "__getitem__"):
return self.names[node.id]
- elif callable(self.names):
+ if callable(self.names):
return self.names(node)
- else:
- raise InvalidExpression(
- 'Trying to use name (variable) "{0}"'
- ' when no "names" defined for'
- " evaluator".format(node.id)
- )
+ raise InvalidExpression(
+ 'Trying to use name (variable) "{0}"'
+ ' when no "names" defined for'
+ " evaluator".format(node.id)
+ )
except KeyError:
if node.id in self.functions:
@@ -523,10 +569,9 @@
def _eval_subscript(self, node):
container = self._eval(node.value)
key = self._eval(node.slice)
- try:
- return container[key]
- except KeyError:
- raise
+ # Currently if there's a KeyError, that gets raised straight up.
+ # TODO: Should that be wrapped in an InvalidExpression?
+ return container[key]
def _eval_attribute(self, node):
for prefix in DISALLOW_PREFIXES:
@@ -595,6 +640,8 @@
function editions. (list, tuple, dict, set).
"""
+ _max_count = 0
+
def __init__(self, operators=None, functions=None, names=None):
super(EvalWithCompoundTypes, self).__init__(operators, functions, names)
@@ -611,18 +658,36 @@
}
)
- def eval(self, expr):
+ def eval(self, expr, previously_parsed=None):
+ # reset _max_count for each eval run
self._max_count = 0
- return super(EvalWithCompoundTypes, self).eval(expr)
+ return super(EvalWithCompoundTypes, self).eval(expr, previously_parsed)
def _eval_dict(self, node):
- return {self._eval(k): self._eval(v) for (k, v) in zip(node.keys, node.values)}
+ result = {}
- def _eval_tuple(self, node):
- return tuple(self._eval(x) for x in node.elts)
+ for key, value in zip(node.keys, node.values):
+ if PYTHON35 and key is None:
+ # "{**x}" gets parsed as a key-value pair of (None, Name(x))
+ result.update(self._eval(value))
+ else:
+ result[self._eval(key)] = self._eval(value)
+
+ return result
def _eval_list(self, node):
- return list(self._eval(x) for x in node.elts)
+ result = []
+
+ for item in node.elts:
+ if PYTHON3 and isinstance(item, ast.Starred):
+ result.extend(self._eval(item.value))
+ else:
+ result.append(self._eval(item))
+
+ return result
+
+ def _eval_tuple(self, node):
+ return tuple(self._eval(x) for x in node.elts)
def _eval_set(self, node):
return set(self._eval(x) for x in node.elts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/simpleeval-0.9.12/test_simpleeval.py new/simpleeval-0.9.13/test_simpleeval.py
--- old/simpleeval-0.9.12/test_simpleeval.py 2022-01-15 18:22:19.000000000 +0100
+++ new/simpleeval-0.9.13/test_simpleeval.py 2023-02-17 09:21:11.000000000 +0100
@@ -1,4 +1,4 @@
-# pylint: disable=too-many-public-methods, missing-docstring, too-many-lines, use-of-eval, disallowed-variable, no-self-use
+# pylint: disable=too-many-public-methods, missing-docstring, eval-used, too-many-lines, no-self-use, disallowed-name, unspecified-encoding
"""
Unit tests for simpleeval.
@@ -24,6 +24,7 @@
FunctionNotDefined,
InvalidExpression,
NameNotDefined,
+ OperatorNotDefined,
SimpleEval,
simple_eval,
)
@@ -82,6 +83,13 @@
-10,
)
+ def test_bit_ops(self):
+ self.t("62 ^ 20", 42)
+ self.t("62 ^ 100", 90)
+ self.t("8 | 34", 42)
+ self.t("100 & 63", 36)
+ self.t("~ -43", 42)
+
def test_not(self):
self.t("not False", True)
self.t("not True", False)
@@ -109,6 +117,7 @@
self.t("1 < 2 < 3 < 4", 1 < 2 < 3 < 4)
self.t("1 < 2 > 3 < 4", 1 < 2 > 3 < 4)
+ # pylint: disable=comparison-with-itself
self.t("1<2<1+1", 1 < 2 < 1 + 1)
self.t("1 == 1 == 2", 1 == 1 == 2)
self.t("1 == 1 < 2", 1 == 1 < 2)
@@ -189,6 +198,49 @@
with self.assertRaises(FeatureNotAvailable):
self.t("{22}", False)
+ def test_empty_string_not_allowed(self):
+ with self.assertRaises(InvalidExpression):
+ self.t("", False)
+
+
+class TestEvaluator(DRYTest):
+ """Tests for how the SimpleEval class does things"""
+
+ def test_only_evalutate_first_statement(self):
+ # it only evaluates the first statement:
+ with warnings.catch_warnings(record=True) as ws:
+ self.t("11; x = 21; x + x", 11)
+ self.assertIsInstance(ws[0].message, simpleeval.MultipleExpressions)
+
+ def test_parse_and_use_previously_parsed(self):
+ expr = "x + x"
+ nodes = self.s.parse(expr)
+ self.s.names = {"x": 21}
+ self.assertEqual(self.s.eval(expr, nodes), 42)
+
+ # This can all be done with unittest.mock.patch in python3.3+ - when we drop
+ # python2 - we can drop this nonsense.
+ class MockedCalled(Exception):
+ pass
+
+ def go_boom(*args, **kwargs):
+ raise MockedCalled("you should never see this.")
+
+ self.s.parse = go_boom
+
+ # Prove the mock is installed in self.s
+ with self.assertRaises(MockedCalled):
+ self.s.eval("10 + 10")
+
+ # Prove it's not installed in the actual SimpleEval
+ SimpleEval().eval("10 + 10")
+
+ # Now running .eval with a previously parsed
+ self.assertEqual(self.s.eval(expr, previously_parsed=nodes), 42)
+
+ self.s.names = {"x": 100}
+ self.assertEqual(self.s.eval(expr, nodes), 200)
+
class TestFunctions(DRYTest):
"""Functions for expressions to play with"""
@@ -258,29 +310,29 @@
self.t("foo()", 42)
def test_function_args_required(self):
- def foo(toret):
- return toret
+ def foo(to_return):
+ return to_return
self.s.functions["foo"] = foo
with self.assertRaises(TypeError):
self.t("foo()", 42)
self.t("foo(12)", 12)
- self.t("foo(toret=100)", 100)
+ self.t("foo(to_return=100)", 100)
def test_function_args_defaults(self):
- def foo(toret=9999):
- return toret
+ def foo(to_return=9999):
+ return to_return
self.s.functions["foo"] = foo
self.t("foo()", 9999)
self.t("foo(12)", 12)
- self.t("foo(toret=100)", 100)
+ self.t("foo(to_return=100)", 100)
def test_function_args_bothtypes(self):
- def foo(mult, toret=100):
- return toret * mult
+ def foo(mult, to_return=100):
+ return to_return * mult
self.s.functions["foo"] = foo
with self.assertRaises(TypeError):
@@ -289,10 +341,10 @@
self.t("foo(2)", 200)
with self.assertRaises(TypeError):
- self.t("foo(toret=100)", 100)
+ self.t("foo(to_return=100)", 100)
- self.t("foo(4, toret=4)", 16)
- self.t("foo(mult=2, toret=4)", 8)
+ self.t("foo(4, to_return=4)", 16)
+ self.t("foo(mult=2, to_return=4)", 8)
self.t("foo(2, 10)", 20)
@@ -328,7 +380,7 @@
"""exponent operations can take a long time."""
old_max = simpleeval.MAX_POWER
- self.t("9**9**5", 9 ** 9 ** 5)
+ self.t("9**9**5", 9**9**5)
with self.assertRaises(simpleeval.NumberTooHigh):
self.t("9**9**8", 0)
@@ -350,8 +402,14 @@
self.t("1<<25000", 0)
with self.assertRaises(simpleeval.NumberTooHigh):
+ self.t("%s<<25" % (simpleeval.MAX_SHIFT_BASE + 1), 0)
+
+ with self.assertRaises(simpleeval.NumberTooHigh):
self.t("1>>25000", 0)
+ with self.assertRaises(simpleeval.NumberTooHigh):
+ self.t("%s>>25" % (simpleeval.MAX_SHIFT_BASE + 1), 0)
+
# and test we can change it:
old_max = simpleeval.MAX_SHIFT
@@ -420,11 +478,6 @@
with self.assertRaises(simpleeval.IterableTooLong):
self.t("('spam spam spam' * 5000).split() * 5000", None)
- def test_python_stuff(self):
- """other various pythony things."""
- # it only evaluates the first statement:
- self.t("11; x = 21; x + x", 11)
-
def test_function_globals_breakout(self):
"""by accessing function.__globals__ or func_..."""
# thanks perkinslr.
@@ -559,6 +612,24 @@
self.t('{"a": 24}.get("b", 11)', 11)
self.t('"a" in {"a": 24}', True)
+ @unittest.skipIf(not simpleeval.PYTHON35, "feature not supported")
+ def test_dict_star_expression(self):
+ self.s.names["x"] = {"a": 1, "b": 2}
+ self.t('{"a": 0, **x, "c": 3}', {"a": 1, "b": 2, "c": 3})
+
+ # and multiple star expressions should be fine too...
+ self.s.names["y"] = {"x": 1, "y": 2}
+ self.t('{"a": 0, **x, **y, "c": 3}', {"a": 1, "b": 2, "c": 3, "x": 1, "y": 2})
+
+ @unittest.skipIf(not simpleeval.PYTHON35, "feature not supported")
+ def test_dict_invalid_star_expression(self):
+ self.s.names["x"] = {"a": 1, "b": 2}
+ self.s.names["y"] = {"x": 1, "y": 2}
+ self.s.names["z"] = 42
+
+ with self.assertRaises(TypeError):
+ self.t('{"a": 0, **x, **y, **z, "c": 3}', {"a": 1, "b": 2, "c": 3})
+
def test_tuple(self):
self.t("()", ())
self.t("(1,)", (1,))
@@ -589,6 +660,19 @@
self.t('"b" in ["a","b"]', True)
+ @unittest.skipIf(not simpleeval.PYTHON3, "feature not supported")
+ def test_list_star_expression(self):
+ self.s.names["x"] = [1, 2, 3]
+ self.t('["a", *x, "b"]', ["a", 1, 2, 3, "b"])
+
+ @unittest.skipIf(not simpleeval.PYTHON3, "feature not supported")
+ def test_list_invalid_star_expression(self):
+ self.s.names["x"] = [1, 2, 3]
+ self.s.names["y"] = 42
+
+ with self.assertRaises(TypeError):
+ self.t('["a", *x, *y, "b"]', ["a", 1, 2, 3, "b"])
+
def test_set(self):
self.t("{1}", {1})
self.t("{1, 2, 1, 2, 1, 2, 1}", {1, 2})
@@ -708,9 +792,11 @@
self.s.names["s"] = 21
+ # or if you attempt to assign an unknown name to another
with self.assertRaises(NameNotDefined):
with warnings.catch_warnings(record=True) as ws:
self.t("s += a", 21)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.s.names = None
@@ -735,6 +821,7 @@
# however, you can't assign to those names:
with warnings.catch_warnings(record=True) as ws:
self.t("a = 200", 200)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.assertEqual(self.s.names["a"], 42)
@@ -744,6 +831,7 @@
with warnings.catch_warnings(record=True) as ws:
self.t("b[0] = 11", 11)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.assertEqual(self.s.names["b"], [0])
@@ -766,6 +854,7 @@
with warnings.catch_warnings(record=True) as ws:
self.t("c['b'] = 99", 99)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.assertFalse("b" in self.s.names["c"])
@@ -775,6 +864,7 @@
with warnings.catch_warnings(record=True) as ws:
self.t("c['c']['c'] = 21", 21)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.assertEqual(self.s.names["c"]["c"]["c"], 11)
@@ -789,6 +879,7 @@
with warnings.catch_warnings(record=True) as ws:
self.t("a.b.c = 11", 11)
+ self.assertIsInstance(ws[0].message, simpleeval.AssignmentAttempted)
self.assertEqual(self.s.names["a"]["b"]["c"], 42)
@@ -816,6 +907,7 @@
def test_object(self):
"""using an object for name lookup"""
+ # pylint: disable=attribute-defined-outside-init
class TestObject(object):
@staticmethod
@@ -1032,10 +1124,12 @@
return BinaryExpression("LT")
b = Blah()
- self.s.names = {"b": b}
- # This should not crash:
- e = eval("b > 2", self.s.names)
+ # These should not crash:
+ self.assertEqual(b > 2, BinaryExpression("GT"))
+ self.assertEqual(b < 2, BinaryExpression("LT"))
+ # And should also work in simpleeval
+ self.s.names = {"b": b}
self.t("b > 2", BinaryExpression("GT"))
self.t("1 < 5 > b", BinaryExpression("LT"))
@@ -1056,7 +1150,7 @@
self.assertEqual(m.anything, 42)
with self.assertRaises(NotImplementedError):
- m["nothing"]
+ m["nothing"] # pylint: disable=pointless-statement
self.s.names = {"m": m}
self.t("m.anything", 42)
@@ -1108,6 +1202,7 @@
def test_functions_are_disallowed_at_init(self):
DISALLOWED = [type, isinstance, eval, getattr, setattr, help, repr, compile, open]
if simpleeval.PYTHON3:
+ # pylint: disable=exec-used
exec("DISALLOWED.append(exec)") # exec is not a function in Python2...
for f in simpleeval.DISALLOW_FUNCTIONS:
@@ -1115,12 +1210,13 @@
for x in DISALLOWED:
with self.assertRaises(FeatureNotAvailable):
- s = SimpleEval(functions={"foo": x})
+ SimpleEval(functions={"foo": x})
def test_functions_are_disallowed_in_expressions(self):
DISALLOWED = [type, isinstance, eval, getattr, setattr, help, repr, compile, open]
if simpleeval.PYTHON3:
+ # pylint: disable=exec-used
exec("DISALLOWED.append(exec)") # exec is not a function in Python2...
for f in simpleeval.DISALLOW_FUNCTIONS:
@@ -1138,11 +1234,13 @@
simpleeval.DEFAULT_FUNCTIONS = DF.copy()
-(a)unittest.skipIf(simpleeval.PYTHON3 != True, "Python2 fails - but it's not supported anyway.")
+(a)unittest.skipIf(simpleeval.PYTHON3 is not True, "Python2 fails - but it's not supported anyway.")
@unittest.skipIf(platform.python_implementation() == "PyPy", "GC set_debug not available in PyPy")
class TestReferenceCleanup(DRYTest):
"""Test cleanup without cyclic references"""
+ # pylint: disable=attribute-defined-outside-init
+
def setUp(self):
self._initial_gc_isenabled = gc.isenabled()
@@ -1165,5 +1263,35 @@
simpleeval.SimpleEval()
+class TestNoEntries(DRYTest):
+ def test_no_functions(self):
+ self.s.eval("int(42)")
+ with self.assertRaises(FunctionNotDefined):
+ s = SimpleEval(functions={})
+ s.eval("int(42)")
+
+ def test_no_names(self):
+ # does not work on current Py3, True et al. are keywords now
+ self.s.eval("True")
+ # with self.assertRaises(NameNotDefined):
+ s = SimpleEval(names={})
+ if sys.version_info < (3,):
+ with self.assertRaises(NameNotDefined):
+ s.eval("True")
+ else:
+ s.eval("True")
+
+ def test_no_operators(self):
+ self.s.eval("1+2")
+ self.s.eval("~2")
+ s = SimpleEval(operators={})
+
+ with self.assertRaises(OperatorNotDefined):
+ s.eval("1+2")
+
+ with self.assertRaises(OperatorNotDefined):
+ s.eval("~ 2")
+
+
if __name__ == "__main__": # pragma: no cover
unittest.main()
1
0
Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package PrusaSlicer for openSUSE:Factory checked in at 2024-01-03 12:23:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/PrusaSlicer (Old)
and /work/SRC/openSUSE:Factory/.PrusaSlicer.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "PrusaSlicer"
Wed Jan 3 12:23:53 2024 rev:31 rq:1135619 version:2.7.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/PrusaSlicer/PrusaSlicer.changes 2023-09-20 13:25:05.237827360 +0200
+++ /work/SRC/openSUSE:Factory/.PrusaSlicer.new.28375/PrusaSlicer.changes 2024-01-03 12:23:56.273175140 +0100
@@ -1,0 +2,52 @@
+Fri Dec 29 09:47:16 UTC 2023 - Ben Greiner <code(a)bnavigator.de>
+
+- Add PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch
+ * Fixes a compilation error with wxWidgets 3.2.4
+ * gh#prusa3d/PrusaSlicer#11769
+
+-------------------------------------------------------------------
+Mon Dec 25 13:59:05 UTC 2023 - Ben Greiner <code(a)bnavigator.de>
+
+- Update to 2.7.1
+ ## Improvements fixed with respect to 2.7.0
+ * The option Export as binary G-code was removed from Print
+ Settings. Instead, there is a new option in Printer Settings
+ named Supports binary G-code so it can be set at printer level.
+ There is also a new global switch in Preferences->Other, which
+ controls whether binary G-code will be generated for printers
+ which support it. It is therefore easy to turn the feature on
+ or off without doing any changes in profiles (#11734, #11873).
+ * Wipe tower weight was added into G-code metadata so it can be
+ easily displayed in the print statistics on the printer's
+ display.
+ ## Bugs fixed with respect to 2.7.0
+ * When ramping travels were enabled, sometimes a perimeter was
+ missing at the layer where the spiral starts.
+ * Fixed a crash when selecting embossed text while an SVG tool is
+ opened (#11759).
+ * Helical layer changes could result in out of bed moves
+ (#11754).
+ * Helical layer change was enabled even when there was no
+ retraction on layer change (#11709, #11761).
+- Release 2.7.0
+ * This is the stable release of PrusaSlicer 2.7.0, introducing
+ SVG emboss, binary G-codes, ramping travels, support for G2/G3
+ G-codes, support for Cancel object function and much more. It
+ also fixes many bugs.
+ * Important note for Original Prusa MINI, MK4 and XL owners: The
+ new configuration update of our system profiles will enable
+ binary G-code and G2/G3 features. Users using older firmware
+ need to update to 5.1.0-alpha2 or later or manually turn these
+ features off. On older firmware, new binary G-code is not
+ visible or recognized and the G2/G3 G-codes may not work
+ perfectly.
+ * Travel moves improvements
+ * SVG embossing tool (#6916, #9373)
+ * G2 and G3 G-code support #4352
+ * Binary G-code
+ * Improved user interface
+ * Custom G-code editor
+ * Cancel object (Marlin, RRF and Klipper)
+- D PrusaSlicer-2.6.0-wxWidgets-CheckResizerFlags-assert-fix.patch
+
+-------------------------------------------------------------------
Old:
----
PrusaSlicer-2.6.0-wxWidgets-CheckResizerFlags-assert-fix.patch
PrusaSlicer-version_2.6.1.tar.gz
New:
----
PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch
PrusaSlicer-version_2.7.1.tar.gz
BETA DEBUG BEGIN:
Old: * Cancel object (Marlin, RRF and Klipper)
- D PrusaSlicer-2.6.0-wxWidgets-CheckResizerFlags-assert-fix.patch
BETA DEBUG END:
BETA DEBUG BEGIN:
New:
- Add PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch
* Fixes a compilation error with wxWidgets 3.2.4
BETA DEBUG END:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ PrusaSlicer.spec ++++++
--- /var/tmp/diff_new_pack.2ApT2z/_old 2024-01-03 12:23:57.353214602 +0100
+++ /var/tmp/diff_new_pack.2ApT2z/_new 2024-01-03 12:23:57.353214602 +0100
@@ -17,19 +17,19 @@
Name: PrusaSlicer
-Version: 2.6.1
+Version: 2.7.1
Release: 0
Summary: G-code generator for 3D printers (RepRap, Makerbot, Ultimaker etc.)
License: AGPL-3.0-only
Group: Hardware/Printing
URL: https://www.prusa3d.com/prusaslicer/
Source0: https://github.com/prusa3d/PrusaSlicer/archive/version_%{version}.tar.gz#/%…
+# PATCH-FIX-UPSTREAM PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch gh#prusa3d/PrusaSlicer#11769
+Patch1: PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch
# PATCH-FIX-OPENSUSE up-occt-version.patch mike.chikov(a)gmail.com -- install wrapper so into libdir, not bindir
-Patch0: up-occt-version.patch
+Patch10: up-occt-version.patch
# PATCH-FIX-OPENSUSE PrusaSlicer-2.6.0-octoprint-name-fix.patch -- cast lambda expression to same type
-Patch1: PrusaSlicer-2.6.0-octoprint-name-fix.patch
-# PATCH-FIX-UPSTREAM PrusaSlicer-2.6.0-wxWidgets-CheckResizerFlags-assert-fix.patch -- https://github.com/prusa3d/PrusaSlicer/pull/10811
-Patch2: PrusaSlicer-2.6.0-wxWidgets-CheckResizerFlags-assert-fix.patch
+Patch11: PrusaSlicer-2.6.0-octoprint-name-fix.patch
BuildRequires: blosc-devel
BuildRequires: cereal-devel
BuildRequires: cgal-devel >= 5.6
@@ -68,6 +68,8 @@
BuildRequires: wxWidgets-devel >= 3.2
# need the fltk fork, see deps/NanoSVG/NanoSVG.cmake
BuildRequires: nanosvg-devel >= 2022.12.22
+BuildRequires: (cmake(Catch2) >= 2.9 with cmake(Catch2) < 3)
+BuildRequires: cmake(LibBGCode)
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(gl)
BuildRequires: pkgconfig(glew)
++++++ PrusaSlicer-2.7.1-slic3r-wxWidgets-3.2.4.patch ++++++
From f67a877d583eba5472003f0ea4df3f7420d70734 Mon Sep 17 00:00:00 2001
From: Gregor Riepl <onitake(a)gmail.com>
Date: Mon, 27 Nov 2023 13:01:55 +0100
Subject: [PATCH] Make initializers explicit to avoid ambiguous wxArrayString
overloads
---
src/slic3r/GUI/PhysicalPrinterDialog.cpp | 2 +-
src/slic3r/GUI/Plater.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp
index 2364c56247..bc2c918a60 100644
--- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp
+++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp
@@ -467,7 +467,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
// Always fill in the "printhost_port" combo box from the config and select it.
{
Choice* choice = dynamic_cast<Choice*>(m_optgroup->get_field("printhost_port"));
- choice->set_values({ m_config->opt_string("printhost_port") });
+ choice->set_values(std::vector<std::string>({ m_config->opt_string("printhost_port") }));
choice->set_selection();
}
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index c2b8e8694f..2f540bfe9d 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -5390,7 +5390,7 @@ void Plater::load_project(const wxString& filename)
p->reset();
- if (! load_files({ into_path(filename) }).empty()) {
+ if (! load_files(std::vector<boost::filesystem::path>({ into_path(filename) })).empty()) {
// At least one file was loaded.
p->set_project_filename(filename);
// Save the names of active presets and project specific config into ProjectDirtyStateManager.
++++++ PrusaSlicer-version_2.6.1.tar.gz -> PrusaSlicer-version_2.7.1.tar.gz ++++++
/work/SRC/openSUSE:Factory/PrusaSlicer/PrusaSlicer-version_2.6.1.tar.gz /work/SRC/openSUSE:Factory/.PrusaSlicer.new.28375/PrusaSlicer-version_2.7.1.tar.gz differ: char 24, line 1
1
0