New Upstream Snapshot - python-sysv-ipc
Ready changes
Summary
Merged new upstream version: 1.0.0+git20210117.3.d8b463a (was: 1.0.0+git20210117.2.d8b463a).
Resulting package
Built on 2022-12-30T17:05 (took 7m50s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-snapshots python3-sysv-ipc-dbgsymapt install -t fresh-snapshots python3-sysv-ipc
Lintian Result
- python-sysv-ipc_1.0.0+git20210117.3.d8b463a-1~jan+nus1.dsc
- python-sysv-ipc_1.0.0+git20210117.3.d8b463a-1~jan+nus1_amd64.buildinfo
- python3-sysv-ipc-dbgsym_1.0.0+git20210117.3.d8b463a-1~jan+nus1_amd64.deb
- python3-sysv-ipc_1.0.0+git20210117.3.d8b463a-1~jan+nus1_amd64.deb
- python-sysv-ipc_1.0.0+git20210117.3.d8b463a-1~jan+nus1_amd64.changes
Diff
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index c5bf870..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-*.pyc
-.DS_Store
-releases/*
-build/*
-dist/*
-probe_results.h
-prober/foo
-prober/0.c
-prober/1.c
-prober/2.c
-notes.txt
-sysv_ipc.egg-info/*
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..ca035ff
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,37 @@
+Metadata-Version: 2.1
+Name: sysv_ipc
+Version: 1.1.0
+Summary: System V IPC primitives (semaphores, shared memory and message queues) for Python
+Home-page: http://semanchuk.com/philip/sysv_ipc/
+Download-URL: http://semanchuk.com/philip/sysv_ipc/sysv_ipc-1.1.0.tar.gz
+Author: Philip Semanchuk
+Author-email: philip@semanchuk.com
+Maintainer: Philip Semanchuk
+License: http://creativecommons.org/licenses/BSD/
+Keywords: sysv ipc inter-process communication semaphore shared memory shm message queue
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: POSIX :: SunOS/Solaris
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Unix
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Utilities
+License-File: LICENSE
+
+Sysv_ipc gives Python programs access to System V semaphores, shared memory
+and message queues. Most (all?) Unixes (including OS X) support System V IPC.
+Windows+Cygwin 1.7 might also work.
+
+Sample code is included.
+
+sysv_ipc is free software (free as in speech and free as in beer) released
+under a 3-clause BSD license. Complete licensing information is available in
+the LICENSE file.
+
+You might also be interested in the similar POSIX IPC module at:
+http://semanchuk.com/philip/posix_ipc/
diff --git a/ReadMe.html b/ReadMe.html
index a1736f7..01c7232 100644
--- a/ReadMe.html
+++ b/ReadMe.html
@@ -1,16 +1,16 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE html>
-<html>
+<html lang='en'>
<head>
<meta charset="utf-8">
<meta name="author" content="Philip Semanchuk">
- <meta name="copyright" content="All contents © 2018 Philip Semanchuk">
+ <meta name="copyright" content="All contents © 2021 Philip Semanchuk">
<meta name="keywords" content="python sysv system v ipc semaphore shared memory message queue">
<title>System V IPC for Python - Semaphores, Shared Memory and Message Queues</title>
- <style type="text/css">
+ <style>
dt {
font-family: monospace;
font-weight: bold;
@@ -45,12 +45,7 @@
<h2>System V IPC for Python - Semaphores, Shared Memory and Message Queues</h2>
-<div class="rss">
- <a href="rss.xml"><img src="/common/images/rss.png" width="28" height="28" alt=""></a>
- <br><a href="rss.xml">RSS</a>
-</div>
-
-<p>This describes the <tt>sysv_ipc</tt> module which gives Python access
+<p>This describes the <code>sysv_ipc</code> module which gives Python access
to System V inter-process semaphores, shared memory and message queues
on most (all?) *nix flavors. Examples include macOS/OS X, Linux, FreeBSD,
OpenSolaris 2008.11, HPUX, and AIX.
@@ -58,17 +53,16 @@ It might also work under Windows with a library like
<a href="http://www.cygwin.com/">Cygwin</a>.
</p>
-<p>It works with Python 2.7 and 3.x.
-It's released
+<p>It works with Python ≥ 3.6. It's released
under a <a href="http://creativecommons.org/licenses/BSD/">BSD license</a>.
</p>
<p>You can <strong>download
-<a href="sysv_ipc-1.0.0.tar.gz">sysv_ipc version 1.0.0</a>
+<a href="sysv_ipc-1.1.0.tar.gz">sysv_ipc version 1.1.0</a>
</strong>
-(<a href="sysv_ipc-1.0.0.md5.txt">[md5 sum]</a>,
-<a href="sysv_ipc-1.0.0.sha1.txt">[sha1 sum]</a>,
-<a href="sysv_ipc-1.0.0.sha256.txt">[sha256 sum]</a>)
+(<a href="sysv_ipc-1.1.0.md5.txt">[md5 sum]</a>,
+<a href="sysv_ipc-1.1.0.sha1.txt">[sha1 sum]</a>,
+<a href="sysv_ipc-1.1.0.sha256.txt">[sha256 sum]</a>)
which contains the source code, setup.py, installation instructions and
<a href="#samples">sample code</a>. You can read about
<a href="history.html#current">all of the changes in this version</a>.
@@ -80,13 +74,13 @@ about some <a href="#bugs">known bugs</a>.
</p>
<p>You might be interested in the very similar module
-<a href="/philip/posix_ipc/"><tt>posix_ipc</tt></a>
+<a href="/philip/posix_ipc/"><code>posix_ipc</code></a>
which provides Python access to POSIX IPC primitives. POSIX IPC is a little
easier to use than SysV IPC, but not all operating systems support it
completely.
</p>
-<h2>Module <tt>sysv_ipc</tt></h2>
+<h2>Module <code>sysv_ipc</code></h2>
<p>Jump to <a href="#semaphore">semaphores</a>,
<a href="#shared_memory">shared memory</a>, or
@@ -97,10 +91,10 @@ completely.
<dl>
<dt>attach(id, [address = None, [flags = 0]])</dt>
- <dd>Attaches the (existing) shared memory that has the given <tt>id</tt> and
+ <dd>Attaches the (existing) shared memory that has the given <code>id</code> and
returns a new SharedMemory object. See
<a href="#attach">SharedMemory.attach()</a> for details on the
- <tt>address</tt> and <tt>flags</tt> parameters.
+ <code>address</code> and <code>flags</code> parameters.
<p>This method is useful only under fairly unusual circumstances.
You probably don't need it.
@@ -108,20 +102,20 @@ completely.
</dd>
<dt>ftok(path, id, [silence_warning = False])</dt>
- <dd>Calls <tt>ftok(path, id)</tt>. Note that
- <a href="#ftok_weakness"><tt>ftok()</tt> has limitations</a>, and this
+ <dd>Calls <code>ftok(path, id)</code>. Note that
+ <a href="#ftok_weakness"><code>ftok()</code> has limitations</a>, and this
function will issue a warning to that effect unless
- <tt>silence_warning</tt> is True.
+ <code>silence_warning</code> is True.
</dd>
<dt>remove_semaphore(id)</dt>
- <dd>Removes the semaphore with the given <tt>id</tt>.</dd>
+ <dd>Removes the semaphore with the given <code>id</code>.</dd>
<dt>remove_shared_memory(id)</dt>
- <dd>Removes the shared memory with the given <tt>id</tt>.</dd>
+ <dd>Removes the shared memory with the given <code>id</code>.</dd>
<dt>remove_message_queue(id)</dt>
- <dd>Removes the message queue with the given <tt>id</tt>.</dd>
+ <dd>Removes the message queue with the given <code>id</code>.</dd>
</dl>
@@ -129,33 +123,33 @@ completely.
<dl>
<dt>IPC_CREAT, IPC_EXCL and IPC_CREX</dt>
- <dd><tt>IPC_CREAT</tt> and <tt>IPC_EXCL</tt> are flags used when
+ <dd><code>IPC_CREAT</code> and <code>IPC_EXCL</code> are flags used when
creating IPC objects. They're
- bitwise unique and can be ORed together. <tt>IPC_CREX</tt> is
- shorthand for <tt>IPC_CREAT | IPC_EXCL</tt>.
+ bitwise unique and can be ORed together. <code>IPC_CREX</code> is
+ shorthand for <code>IPC_CREAT | IPC_EXCL</code>.
- <p>When passed to an IPC object's constructor, <tt>IPC_CREAT</tt> indicates
+ <p>When passed to an IPC object's constructor, <code>IPC_CREAT</code> indicates
that you want to create a new object or open an existing one. If you want
the call to fail if an object with that key already exists, specify
- the <tt>IPC_EXCL</tt> flag, too.
+ the <code>IPC_EXCL</code> flag, too.
</p>
</dd>
<dt>IPC_PRIVATE</dt>
<dd>This is a special value that can be passed in place of a key. It implies that
the IPC object should be available only to the creating process or its
- child processes (e.g. those created with <tt>fork()</tt>).
+ child processes (e.g. those created with <code>fork()</code>).
</dd>
<dt>KEY_MIN and KEY_MAX</dt>
<dd>Denote the range of keys that this module accepts. Your OS might
limit keys to a smaller range depending on the typedef of
- <tt>key_t</tt>.
+ <code>key_t</code>.
<p>Keys randomly generated by this module are in the range
- <tt>1 ≤ key ≤ SHRT_MAX</tt>.
+ <code>1 ≤ key ≤ SHRT_MAX</code>.
That's type-safe unless your OS has a very bizarre
- definition of <tt>key_t</tt>.
+ definition of <code>key_t</code>.
</p>
</dd>
@@ -172,28 +166,28 @@ completely.
<dd>True if the platform supports timed semaphore waits, False otherwise.</dd>
<dt>SHM_RDONLY</dt>
- <dd>Pass this flag to <tt>SharedMemory.attach()</tt> to attach the segment
+ <dd>Pass this flag to <code>SharedMemory.attach()</code> to attach the segment
read-only.</dd>
<dt>SHM_RND</dt>
<dd>You probably don't need this, but it can be used when attaching shared
memory to force the address to be
- rounded down to SHMLBA. See your system's man page for <tt>shmat()</tt>
+ rounded down to SHMLBA. See your system's man page for <code>shmat()</code>
for more information.
</dd>
<dt>SHM_HUGETLB, SHM_NORESERVE and SHM_REMAP</dt>
<dd>You probably don't need these. They're Linux-specific flags that can
be passed to the SharedMemory
- constructor, or to the <tt>.attach()</tt> function in the case of
- SHM_REMAP. See your system's man page for <tt>shmget()</tt>
- and <tt>shmat()</tt> for more information.
+ constructor, or to the <code>.attach()</code> function in the case of
+ SHM_REMAP. See your system's man page for <code>shmget()</code>
+ and <code>shmat()</code> for more information.
</dd>
</dl>
<h3>Module Errors</h3>
-<p>In addition to standard Python errors (e.g. <tt>ValueError</tt>),
+<p>In addition to standard Python errors (e.g. <code>ValueError</code>),
this module raises custom errors. These errors cover
situations specific to IPC.
</p>
@@ -221,8 +215,8 @@ situations specific to IPC.
</dd>
<dt>BusyError</dt>
- <dd>Raised when a semaphore call to <tt>.P()</tt> or <tt>.Z()</tt> either times out
- or would be forced to wait when its <tt>block</tt> attribute is False.
+ <dd>Raised when a semaphore call to <code>.P()</code> or <code>.Z()</code> either times out
+ or would be forced to wait when its <code>block</code> attribute is False.
</dd>
<dt>NotAttachedError</dt>
@@ -242,10 +236,10 @@ situations specific to IPC.
<dt>Semaphore(key, [flags = 0, [mode = 0600, [initial_value = 0]]])</dt>
<dd>Creates a new semaphore or opens an existing one.
- <p><span class="param">key</span> must be <tt>None</tt>,
- <tt>IPC_PRIVATE</tt> or
- an integer > <tt>KEY_MIN</tt> and ≤ <tt>KEY_MAX</tt>. If the key
- is <tt>None</tt>, the module chooses a random unused key.
+ <p><span class="param">key</span> must be <code>None</code>,
+ <code>IPC_PRIVATE</code> or
+ an integer > <code>KEY_MIN</code> and ≤ <code>KEY_MAX</code>. If the key
+ is <code>None</code>, the module chooses a random unused key.
</p>
<p>The <span class="param">flags</span> specify whether you want to create a
@@ -253,24 +247,24 @@ situations specific to IPC.
</p>
<ul>
- <li>With <span class="param">flags</span> set to the <strong>default</strong> of <tt>0</tt>, the module attempts
+ <li>With <span class="param">flags</span> set to the <strong>default</strong> of <code>0</code>, the module attempts
to <strong>open an existing</strong> semaphore identified by <span class="param">key</span> and raises
- a <tt>ExistentialError</tt> if that semaphore doesn't exist.
+ a <code>ExistentialError</code> if that semaphore doesn't exist.
</li>
- <li>With <span class="param">flags</span> set to <tt>IPC_CREAT</tt>, the module
+ <li>With <span class="param">flags</span> set to <code>IPC_CREAT</code>, the module
<strong>opens</strong> the semaphore identified by
<span class="param">key</span> <strong>or creates</strong> a new
- one if no such semaphore exists. Using <tt>IPC_CREAT</tt> by itself
+ one if no such semaphore exists. Using <code>IPC_CREAT</code> by itself
is not recommended. (See <a href="#sem_init">Semaphore Initialization</a>.)
</li>
<li>With <span class="param">flags</span> set to
- <tt>IPC_CREX</tt> (<tt>IPC_CREAT | IPC_EXCL</tt>),
+ <code>IPC_CREX</code> (<code>IPC_CREAT | IPC_EXCL</code>),
the module
<strong>creates a new semaphore</strong> identified by <span class="param">key</span>. If a
semaphore with that key already exists, the call raises an
- <tt>ExistentialError</tt>.
+ <code>ExistentialError</code>.
<strong>The <span class="param">initial_value</span> is ignored unless
both of these flags are specified</strong> or
if the semaphore is read-only.
@@ -299,7 +293,7 @@ situations specific to IPC.
</li>
<li>When <span class="param">timeout</span> is 0, the call
- raises a <tt>BusyError</tt> if it can't immediately
+ raises a <code>BusyError</code> if it can't immediately
acquire the semaphore. Since it will
return immediately if <em>not</em> asked to wait, this can be
thought of as "non-blocking" mode.
@@ -308,25 +302,25 @@ situations specific to IPC.
<li>When the <span class="param">timeout</span> is > 0, the call
will wait no longer than <span class="param">timeout</span>
seconds before either returning (having acquired the semaphore)
- or raising a <tt>BusyError</tt>.
+ or raising a <code>BusyError</code>.
</li>
</ul>
<p>When the call returns, the semaphore's value decreases by
<span class="param">delta</span>
- (or more precisely, <tt>abs(<span class="param">delta</span>)</tt>)
+ (or more precisely, <code>abs(<span class="param">delta</span>)</code>)
which defaults to 1.
</p>
- <p>On platforms that don't support the <tt>semtimedop()</tt> API call,
+ <p>On platforms that don't support the <code>semtimedop()</code> API call,
all timeouts (including zero) are treated as infinite. The call
will not return until its wait condition is satisfied.
</p>
- <p>Most platforms provide <tt>semtimedop()</tt>. macOS is a
+ <p>Most platforms provide <code>semtimedop()</code>. macOS is a
notable exception. The module's Boolean constant
- <tt>SEMAPHORE_TIMEOUT_SUPPORTED</tt>
- is True on platforms that support <tt>semtimedop()</tt>.
+ <code>SEMAPHORE_TIMEOUT_SUPPORTED</code>
+ is True on platforms that support <code>semtimedop()</code>.
</p>
</dd>
@@ -336,13 +330,13 @@ situations specific to IPC.
Releases (increments) the semaphore.
<p>The semaphore's value increases by <span class="param">delta</span>
- (or more precisely, <tt>abs(<span class="param">delta</span>)</tt>)
+ (or more precisely, <code>abs(<span class="param">delta</span>)</code>)
which defaults to 1.
</p>
</dd>
<dt>P()</dt>
- <dd>A synonym for <tt>.acquire()</tt> that takes the same parameters.
+ <dd>A synonym for <code>.acquire()</code> that takes the same parameters.
<p>"P" stands for
<span lang="nl">prolaag</span> or <span lang="nl">probeer te verlagen</span>
@@ -352,7 +346,7 @@ situations specific to IPC.
</dd>
<dt>V()</dt>
- <dd>A synonym for <tt>.release()</tt> that takes the same parameters.
+ <dd>A synonym for <code>.release()</code> that takes the same parameters.
<p>"V" stands for
<span lang="nl">verhoog</span> (increase), the original name given by
@@ -364,7 +358,7 @@ situations specific to IPC.
<dd>Blocks until zee zemaphore is zero.
<p><span class="param">Timeout</span> has
- the same meaning as described in <tt>.acquire()</tt>.
+ the same meaning as described in <code>.acquire()</code>.
</p>
</dd>
@@ -374,7 +368,7 @@ situations specific to IPC.
<p>As far as I can tell, the effect of deleting a semaphore that
other processes are still using is OS-dependent. Check your system's
- man pages for <tt>semctl(IPC_RMID)</tt>.
+ man pages for <code>semctl(IPC_RMID)</code>.
</p>
</dd>
</dl>
@@ -406,8 +400,8 @@ situations specific to IPC.
<dt>block</dt>
<dd>
- Defaults to True, which means that calls to <tt>acquire()</tt> and
- <tt>release()</tt> will not return
+ Defaults to True, which means that calls to <code>acquire()</code> and
+ <code>release()</code> will not return
until their wait conditions are satisfied.
<p>When False, these calls
@@ -421,7 +415,7 @@ situations specific to IPC.
<p>Tip: the following Python code will display
the mode in octal:<br>
- <tt>print int(str(my_sem.mode), 8)</tt>
+ <code>print int(str(my_sem.mode), 8)</code>
</p>
</dd>
@@ -438,8 +432,8 @@ situations specific to IPC.
<dd>The semaphore creator's group id.</dd>
<dt>last_pid (read-only)</dt>
- <dd>The PID of the process that last called <tt>semop()</tt> (<tt>.P()</tt>,
- <tt>.V()</tt> or <tt>.Z()</tt>) on this semaphore.
+ <dd>The PID of the process that last called <code>semop()</code> (<code>.P()</code>,
+ <code>.V()</code> or <code>.Z()</code>) on this semaphore.
<p>Linux and macOS also set this when the semaphore's value is changed,
although doing so disagrees with the POSIX specification.
@@ -449,23 +443,23 @@ situations specific to IPC.
<dt>waiting_for_nonzero (read-only)</dt>
<dd>The number of processes waiting for the value of the semaphore to become
- non-zero (i.e. the number waiting in a call to <tt>.P()</tt>).
+ non-zero (i.e. the number waiting in a call to <code>.P()</code>).
</dd>
<dt>waiting_for_zero (read-only)</dt>
<dd>The number of processes waiting for the value of the semaphore to become
- zero (i.e. the number waiting in a call to <tt>.Z()</tt>).
+ zero (i.e. the number waiting in a call to <code>.Z()</code>).
</dd>
<dt>o_time (read-only)</dt>
- <dd>The last time <tt>semop()</tt> (i.e. <tt>.P()</tt>, <tt>.V()</tt> or
- <tt>.Z()</tt>) was called on this semaphore.
+ <dd>The last time <code>semop()</code> (i.e. <code>.P()</code>, <code>.V()</code> or
+ <code>.Z()</code>) was called on this semaphore.
</dd>
</dl>
<h4>Context Manager Support</h4>
-<p>These semaphores provide <tt>__enter__()</tt> and <tt>__exit__()</tt>
+<p>These semaphores provide <code>__enter__()</code> and <code>__exit__()</code>
methods so they can be used in context managers. For instance --
</p>
@@ -475,7 +469,7 @@ with sysv_ipc.Semaphore(name) as sem:
</pre>
<p>Entering the context acquires the semaphore, exiting the context releases
- the semaphore. See <tt>demo4/child.py</tt> for a complete example.
+ the semaphore. See <code>demo4/child.py</code> for a complete example.
</p>
@@ -487,10 +481,10 @@ with sysv_ipc.Semaphore(name) as sem:
<p>
In addition to the
- methods and attributes described below, <tt>SharedMemory</tt> supports
- Python's buffer protocol, which means you can create <tt>bytearray</tt>
- and <tt>memoryview</tt> objects based on a <tt>SharedMemory</tt> segment.
- See <tt>demos/buffer_protocol</tt> for an example.
+ methods and attributes described below, <code>SharedMemory</code> supports
+ Python's buffer protocol, which means you can create <code>bytearray</code>
+ and <code>memoryview</code> objects based on a <code>SharedMemory</code> segment.
+ See <code>demos/buffer_protocol</code> for an example.
</p>
<h4>Methods</h4>
@@ -500,10 +494,10 @@ with sysv_ipc.Semaphore(name) as sem:
<dd>Creates a new shared memory segment or opens an existing one.
The memory is automatically attached.
- <p><span class="param">key</span> must be <tt>None</tt>,
- <tt>IPC_PRIVATE</tt> or
- an integer > <tt>0</tt> and ≤ <tt>KEY_MAX</tt>. If the key
- is <tt>None</tt>, the module chooses a random unused key.
+ <p><span class="param">key</span> must be <code>None</code>,
+ <code>IPC_PRIVATE</code> or
+ an integer > <code>0</code> and ≤ <code>KEY_MAX</code>. If the key
+ is <code>None</code>, the module chooses a random unused key.
</p>
<p>The <span class="param">flags</span> specify whether you want to create a
@@ -512,29 +506,29 @@ with sysv_ipc.Semaphore(name) as sem:
<ul>
<li>With <span class="param">flags</span> set to the
- <strong>default</strong> of <tt>0</tt>, the module attempts
+ <strong>default</strong> of <code>0</code>, the module attempts
to <strong>open an existing</strong> shared memory segment identified by
<span class="param">key</span> and raises
- a <tt>ExistentialError</tt> if it doesn't exist.
+ a <code>ExistentialError</code> if it doesn't exist.
</li>
- <li>With <span class="param">flags</span> set to <strong><tt>IPC_CREAT</tt></strong>, the module
+ <li>With <span class="param">flags</span> set to <strong><code>IPC_CREAT</code></strong>, the module
<strong>opens</strong> the shared memory segment identified
by <span class="param">key</span> <strong>or
creates</strong> a new one if no such segment exists.
- Using <tt>IPC_CREAT</tt> by itself
+ Using <code>IPC_CREAT</code> by itself
is not recommended. (See <a href="#mem_init">Memory Initialization</a>.)
</li>
<li>With <span class="param">flags</span> set to
- <strong><tt>IPC_CREX</tt></strong> (<tt>IPC_CREAT | IPC_EXCL</tt>),
+ <strong><code>IPC_CREX</code></strong> (<code>IPC_CREAT | IPC_EXCL</code>),
the module
<strong>creates</strong> a new shared memory segment identified by
<span class="param">key</span>. If
a segment with that key already exists, the call raises
- a <tt>ExistentialError</tt>.
+ a <code>ExistentialError</code>.
- <p>When both <tt>IPC_CREX</tt> is specified
+ <p>When both <code>IPC_CREX</code> is specified
and the caller has write permission, each byte in the new memory segment will be
initialized to the value of <span class="param">init_character</span>.
</p>
@@ -552,43 +546,43 @@ with sysv_ipc.Semaphore(name) as sem:
<li>When creating an new segment,
many (most? all?) operating systems insist on a <span class="param">size</span>
- > <tt>0</tt>.
+ > <code>0</code>.
In addition, some round the size
up to the next multiple of PAGE_SIZE.
</li>
</ul>
<p>This module supplies a default
- <span class="param">size</span> of <tt>PAGE_SIZE</tt> when
- <tt>IPC_CREX</tt> is specified and <tt>0</tt> otherwise.
+ <span class="param">size</span> of <code>PAGE_SIZE</code> when
+ <code>IPC_CREX</code> is specified and <code>0</code> otherwise.
</p>
</dd>
<dt id="attach">attach([address = None, [flags = 0]])</dt>
<dd>
Attaches this process to the shared memory. The memory must be attached
- before calling <tt>.read()</tt> or <tt>.write()</tt>. Note that the
+ before calling <code>.read()</code> or <code>.write()</code>. Note that the
constructor automatically attaches the memory
so you won't need to call this method unless you explicitly detach it
and then want to use it again.
<p>The address parameter allows one to specify (as a Python long) a memory
address at which to attach the segment. Passing None (the default)
- is equivalent to passing NULL to <tt>shmat()</tt>. See that
+ is equivalent to passing NULL to <code>shmat()</code>. See that
function's man page for details.
</p>
<p>The flags are mostly only relevant if one specifies a specific address.
- One exception is the flag <tt>SHM_RDONLY</tt> which, surprisingly,
+ One exception is the flag <code>SHM_RDONLY</code> which, surprisingly,
attaches the segment read-only.
</p>
- <p>Note that on some (and perhaps all) platforms, each call to <tt>.attach()</tt>
+ <p>Note that on some (and perhaps all) platforms, each call to <code>.attach()</code>
increments the system's "attached" count. Thus, if each call to
- <tt>.attach()</tt> isn't paired with a call to <tt>.detach()</tt>,
+ <code>.attach()</code> isn't paired with a call to <code>.detach()</code>,
the system's "attached" count for the shared memory segment will not
go to zero when the process exits. As a result, the shared memory
- segment may not disappear even when its creator calls <tt>.remove()</tt>
+ segment may not disappear even when its creator calls <code>.remove()</code>
and exits.
</p>
</dd>
@@ -599,7 +593,7 @@ with sysv_ipc.Semaphore(name) as sem:
<dt>read([byte_count = 0, [offset = 0]])</dt>
<dd>Reads up to <span class="param">byte_count</span> bytes from the
shared memory segment starting at <span class="param">offset</span>
- and returns them as a bytes object (which is the same as a <tt>str</tt>
+ and returns them as a bytes object (which is the same as a <code>str</code>
under Python 2).
<p>If <span class="param">byte_count</span> is zero (the default) the
@@ -615,16 +609,16 @@ with sysv_ipc.Semaphore(name) as sem:
</dd>
<dt>write(some_bytes, [offset = 0])</dt>
- <dd>Writes bytes (i.e. <tt>str</tt> in Python 2) to the shared memory,
+ <dd>Writes bytes (i.e. <code>str</code> in Python 2) to the shared memory,
starting at <span class="param">offset</span>. Passing a Unicode object
may work, but doing so is unsupported and may be explicitly deprecated
in a future version.
<p>If the offset + data would write outside of the segment,
- this function raises <tt>ValueError</tt>.
+ this function raises <code>ValueError</code>.
</p>
- <p>The bytes may contain embedded NULL bytes ('\0').
+ <p>The bytes may contain embedded NULL bytes (<code>'\0'</code>).
</dd>
<dt>remove()</dt>
@@ -681,7 +675,7 @@ with sysv_ipc.Semaphore(name) as sem:
<p>Tip: the following Python code will display
the mode in octal:<br>
- <tt>print int(str(my_mem.mode), 8)</tt>
+ <code>print int(str(my_mem.mode), 8)</code>
</p>
</dd>
@@ -703,10 +697,10 @@ with sysv_ipc.Semaphore(name) as sem:
<dt>MessageQueue(key, [flags = 0, [mode = 0600, [max_message_size = 2048]]])</dt>
<dd>Creates a new message queue or opens an existing one.
- <p><span class="param">key</span> must be <tt>None</tt>,
- <tt>IPC_PRIVATE</tt> or
- an integer > <tt>0</tt> and ≤ <tt>KEY_MAX</tt>. If the key
- is <tt>None</tt>, the module chooses a random unused key.
+ <p><span class="param">key</span> must be <code>None</code>,
+ <code>IPC_PRIVATE</code> or
+ an integer > <code>0</code> and ≤ <code>KEY_MAX</code>. If the key
+ is <code>None</code>, the module chooses a random unused key.
</p>
<p>The <span class="param">flags</span> specify whether you want to create a
@@ -715,25 +709,25 @@ with sysv_ipc.Semaphore(name) as sem:
<ul>
<li>With <span class="param">flags</span> set to the
- <strong>default</strong> of <tt>0</tt>, the module attempts
+ <strong>default</strong> of <code>0</code>, the module attempts
to <strong>open an existing</strong> message queue identified by
<span class="param">key</span> and raises
- a <tt>ExistentialError</tt> if it doesn't exist.
+ a <code>ExistentialError</code> if it doesn't exist.
</li>
- <li>With <span class="param">flags</span> set to <strong><tt>IPC_CREAT</tt></strong>, the module
+ <li>With <span class="param">flags</span> set to <strong><code>IPC_CREAT</code></strong>, the module
<strong>opens</strong> the message queue identified
by <span class="param">key</span> <strong>or
creates</strong> a new one if no such queue exists.
</li>
<li>With <span class="param">flags</span> set to
- <strong><tt>IPC_CREX</tt></strong> (<tt>IPC_CREAT | IPC_EXCL</tt>),
+ <strong><code>IPC_CREX</code></strong> (<code>IPC_CREAT | IPC_EXCL</code>),
the module
<strong>creates</strong> a new message queue identified by
<span class="param">key</span>. If
a queue with that key already exists, the call raises
- a <tt>ExistentialError</tt>.
+ a <code>ExistentialError</code>.
</li>
</ul>
@@ -747,8 +741,8 @@ with sysv_ipc.Semaphore(name) as sem:
<dd>Puts a message on the queue.
<p>The <span class="param">message</span> should be a bytes object
- (a.k.a. <tt>str</tt> in Python 2) and can contain embedded
- NULLs (ASCII <tt>0x00</tt>). Passing a Unicode object
+ (a.k.a. <code>str</code> in Python 2) and can contain embedded
+ NULLs (ASCII <code>0x00</code>). Passing a Unicode object
may work, but doing so is unsupported and may be explicitly deprecated
in a future version.
</p>
@@ -756,26 +750,26 @@ with sysv_ipc.Semaphore(name) as sem:
<p>The <span class="param">block</span> flag specifies whether or
not the call should wait if the message can't be sent (if, for
example, the queue is full). When <span class="param">block</span>
- is <tt>False</tt>, the call will raise a <tt>BusyError</tt> if
+ is <code>False</code>, the call will raise a <code>BusyError</code> if
the message can't be sent immediately.
</p>
<p>The <span class="param">type</span> is
associated with the message and is relevant when calling
- <tt>receive()</tt>. It must be > 0.
+ <code>receive()</code>. It must be > 0.
</p>
</dd>
<dt>receive([block = True, [type = 0]])</dt>
<dd>
Receives a message from the queue, returning a tuple of
- <tt>(message, type)</tt>. The message is a bytes object
- (a.k.a. <tt>str</tt> in Python 2).
+ <code>(message, type)</code>. The message is a bytes object
+ (a.k.a. <code>str</code> in Python 2).
<p>The <span class="param">block</span> flag specifies whether or
not the call should wait if there's no messages of the
specified type to retrieve. When <span class="param">block</span>
- is <tt>False</tt>, the call will raise a <tt>BusyError</tt> if
+ is <code>False</code>, the call will raise a <code>BusyError</code> if
a message can't be received immediately.
</p>
@@ -784,14 +778,14 @@ with sysv_ipc.Semaphore(name) as sem:
</p>
<ul>
- <li>When <span class="param">type</span> <tt>== 0</tt>, the call
+ <li>When <span class="param">type</span> <code>== 0</code>, the call
returns the first message on the queue regardless of its
type.
</li>
- <li>When <span class="param">type</span> <tt>> 0</tt>, the call
+ <li>When <span class="param">type</span> <code>> 0</code>, the call
returns the first message of that type.
</li>
- <li>When <span class="param">type</span> <tt>< 0</tt>, the call
+ <li>When <span class="param">type</span> <code>< 0</code>, the call
returns the first message of the lowest type that is ≤ the
absolute value of <span class="param">type</span>.
</li>
@@ -847,7 +841,7 @@ with sysv_ipc.Semaphore(name) as sem:
<p>Tip: the following Python code will display
the mode in octal:<br>
- <tt>print int(str(my_mem.mode), 8)</tt>
+ <code>print int(str(my_mem.mode), 8)</code>
</p>
</dd>
@@ -863,61 +857,61 @@ with sysv_ipc.Semaphore(name) as sem:
<h4 id='samples'>Sample Code</h4>
<p>This module comes with four sets of demonstration code in the
-directory <tt>demos</tt>.</p>
+directory <code>demos</code>.</p>
<ul>
- <li><tt>sem_and_shm</tt> demonstrates using semaphores and
+ <li><code>sem_and_shm</code> demonstrates using semaphores and
shared memory to share data between processes.
</li>
- <li><tt>message_queues</tt> demonstrates using message queues
+ <li><code>message_queues</code> demonstrates using message queues
to share data between processes.
</li>
- <li><tt>buffer_protocol</tt> demonstrates creating <tt>bytearray</tt> and
- <tt>memoryview</tt> objects atop shared memory.
+ <li><code>buffer_protocol</code> demonstrates creating <code>bytearray</code> and
+ <code>memoryview</code> objects atop shared memory.
</li>
- <li><tt>semaphore_context_manager</tt> demonstrates using
- semaphore instances in a context manager (<tt>with</tt> statement).
+ <li><code>semaphore_context_manager</code> demonstrates using
+ semaphore instances in a context manager (<code>with</code> statement).
</li>
</ul>
-<h4 id="ftok_weakness">The Weakness of <tt>ftok()</tt></h4>
+<h4 id="ftok_weakness">The Weakness of <code>ftok()</code></h4>
<p>
-Most System V IPC sample code recommends <tt>ftok()</tt> for generating an
+Most System V IPC sample code recommends <code>ftok()</code> for generating an
integer key that's more-or-less random.
It does not, however, guarantee that the key it generates is unused. If
-<tt>ftok()</tt> gives your application a key that some other application is
+<code>ftok()</code> gives your application a key that some other application is
already using,
your app is in trouble unless it has a reliable second mechanism for generating
-a key. And if that's the case, why not just abandon <tt>ftok()</tt> and use the
+a key. And if that's the case, why not just abandon <code>ftok()</code> and use the
second mechanism exclusively?
</p>
-<p>This is the weakness of <tt>ftok()</tt> -- it isn't guaranteed to give you
+<p>This is the weakness of <code>ftok()</code> -- it isn't guaranteed to give you
what you want. The <a href="http://www.unix.com/man-page/FreeBSD/3/ftok/">BSD
-man page for <tt>ftok</tt></a> says it is "quite possible for the routine to
+man page for <code>ftok</code></a> says it is "quite possible for the routine to
return duplicate keys". The term "quite possible" isn't quantified, but suppose
it means one-tenth of one percent. Who wants to have 1-in-1000 odds of a
catastrophic failure in their program, or even 1-in-10000?
</p>
-<p>This module obviates the need for <tt>ftok()</tt> by generating random
-keys for you. If your application can't use <tt>sysv_ipc</tt>'s automatically
+<p>This module obviates the need for <code>ftok()</code> by generating random
+keys for you. If your application can't use <code>sysv_ipc</code>'s automatically
generated keys because it needs to know the key in advance, hardcoding a
random number like 123456 in your app might be no worse than using
-<tt>ftok()</tt> and has the advantage of not hiding its limitations.
+<code>ftok()</code> and has the advantage of not hiding its limitations.
</p>
-<p>This module provides <tt>ftok()</tt> in case you want to experiment with it.
-However, to emphasize its weakness, this version of <tt>ftok()</tt> raises a
+<p>This module provides <code>ftok()</code> in case you want to experiment with it.
+However, to emphasize its weakness, this version of <code>ftok()</code> raises a
warning with every call unless you explicitly pass a flag to silence it.
</p>
-<p>This package also provides <tt>ftok_experiment.py</tt> so that you can observe
-how often <tt>ftok()</tt> generates duplicate keys on your system.
+<p>This package also provides <code>ftok_experiment.py</code> so that you can observe
+how often <code>ftok()</code> generates duplicate keys on your system.
</p>
@@ -926,7 +920,7 @@ how often <tt>ftok()</tt> generates duplicate keys on your system.
<p>When a System V sempahore is created at the C API level, the OS is not required
to initialize the semaphore's value. (This per
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/semget.html">the
-SUSv3 standard for <tt>semget()</tt></a>.)
+SUSv3 standard for <code>semget()</code></a>.)
Some (most? all?) operating systems initialize it to zero, but this behavior
is non-standard and therefore can't be relied upon.
</p>
@@ -934,11 +928,11 @@ is non-standard and therefore can't be relied upon.
<p>If sempahore creation happens in an predictable, orderly fashion, this isn't a
problem. But a
race condition arises when multiple processes vie to create/open the same semaphore. The
-problem lies in the fact that when an application calls <tt>semget()</tt> with only
-the <tt>IPC_CREAT</tt> flag, the caller can't tell whether or not he has
+problem lies in the fact that when an application calls <code>semget()</code> with only
+the <code>IPC_CREAT</code> flag, the caller can't tell whether or not he has
created a new semaphore or opened an existing one.
<strong>This makes it
-difficult to create reliable code without using <tt>IPC_EXCL</tt>.</strong>
+difficult to create reliable code without using <code>IPC_EXCL</code>.</strong>
W. Richard Stevens' <span class='book_title'>Unix Network Programming Volume 2</span>
calls this "a fatal flaw in the design of System V semaphores" (p 284).
</p>
@@ -950,24 +944,24 @@ Consider the following sequence of events at the startup of P1 and P2 –
</p>
<ol>
- <li>P1 calls <tt>semget(IPC_CREAT)</tt> to create the semaphore S.</li>
- <li>P2 calls <tt>semget(IPC_CREAT)</tt> to open S.</li>
+ <li>P1 calls <code>semget(IPC_CREAT)</code> to create the semaphore S.</li>
+ <li>P2 calls <code>semget(IPC_CREAT)</code> to open S.</li>
<li>P1 initializes the semaphore's value to 1.</li>
- <li>P1 calls <tt>acquire()</tt>, decrementing the value to 0.</li>
+ <li>P1 calls <code>acquire()</code>, decrementing the value to 0.</li>
<li>P2, assuming S is a newly-created semaphore that needs to be initialized,
incorrectly sets the semaphore's value to 1.</li>
- <li>P2 calls <tt>acquire()</tt>, decrementing the value to 0. Both processes
+ <li>P2 calls <code>acquire()</code>, decrementing the value to 0. Both processes
now think they own the lock.</li>
</ol>
<p>W. Richard Stevens' solution for this race condition is to check the value of
-<tt>sem_otime</tt> (an element in the <tt>semid_ds</tt> struct that's
-populated on the call to <tt>semctl(IPC_STAT)</tt> and which is exposed to
+<code>sem_otime</code> (an element in the <code>semid_ds</code> struct that's
+populated on the call to <code>semctl(IPC_STAT)</code> and which is exposed to
Python by this module) which
is initialized to zero when the semaphore is created and otherwise holds
the time of the last
-call to <tt>semop()</tt> (which is called by <tt>P()</tt>/<tt>acquire()</tt>,
-<tt>V()</tt>/<tt>release()</tt>, and <tt>Z()</tt>).
+call to <code>semop()</code> (which is called by <code>P()</code>/<code>acquire()</code>,
+<code>V()</code>/<code>release()</code>, and <code>Z()</code>).
</p>
<p>In Python, each process would run something like this:
@@ -990,7 +984,7 @@ else:
<h4 id="mem_init">Shared Memory Initialization</h4>
<p>With shared memory,
-using the <tt>IPC_CREAT</tt> flag without <tt>IPC_EXCL</tt>
+using the <code>IPC_CREAT</code> flag without <code>IPC_EXCL</code>
is problematic <em>unless you know the size of the segment
you're potentially opening</em>.
</p>
@@ -999,14 +993,14 @@ you're potentially opening</em>.
many (most? all?) operating systems demand a non-zero size. However,
when opening an existing segment, zero is the only guaranteed safe value
(again, assuming one doesn't know the size of the segment in advance).
-Since <tt>IPC_CREAT</tt>
+Since <code>IPC_CREAT</code>
can open or create a segment, there's no safe value for the size under
this circumstance.
</p>
<p>As a (sort of) side note, the
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/shmget.html">SUSv3
-specification for <tt>shmget()</tt></a> says only that the size of a new
+specification for <code>shmget()</code></a> says only that the size of a new
segment must not be less than "the system-imposed minimum". I
gather that at one time, some systems set the minimum at zero despite the
fact that it doesn't make much sense to create a zero-length shared memory
@@ -1039,7 +1033,7 @@ a recompile.
<p><strong>This module can't figure out what the limits are</strong>, so
it can't cushion them or even report them to you.
On some systems the limits are expressed in header files, on others
-they're available through kernel interfaces (like FreeBSD's <tt>sysctl</tt>).
+they're available through kernel interfaces (like FreeBSD's <code>sysctl</code>).
Under macOS and to some extent OpenSolaris I can't figure out where they're
defined and what I report here is the result of experimentation and educated
guesses formed by Googling.
@@ -1047,7 +1041,7 @@ guesses formed by Googling.
<p>The good news is that this module will still behave as advertised no
matter what these limits are. Nevertheless you might be surprised when a
-call to <tt>.send()</tt> get stuck because a queue is full even though you've
+call to <code>.send()</code> get stuck because a queue is full even though you've
only put 2048 bytes of messages in it.
</p>
@@ -1060,7 +1054,7 @@ improved over the 2009 numbers I describe below.
<p>Under <strong>OpenSolaris 2008.05</strong> each queue's maximum size defaults
to 64k. A privileged process (e.g. root) can change this through the
-<tt>max_size</tt> attribute of a <tt>sysv_ipc.MessageQueue</tt> object.
+<code>max_size</code> attribute of a <code>sysv_ipc.MessageQueue</code> object.
I was able to increase it to 16M and successfully sent sixteen 1M messages to
the queue.
</p>
@@ -1072,7 +1066,7 @@ increase this to 16M, but only for a privileged process.
<p>Under <strong>FreeBSD 7</strong> and I think NetBSD and OpenBSD, each
queue's maximum size defaults to 2048 bytes. Furthermore, one can (as root)
-set <tt>max_size</tt> to something larger and FreeBSD doesn't complain, but
+set <code>max_size</code> to something larger and FreeBSD doesn't complain, but
it also ignores the change.
</p>
@@ -1087,8 +1081,8 @@ message queue limits</a>.
<p>If you want
to search for these limits on your operating system, the key constants are
-<tt>MSGSEG</tt>, <tt>MSGSSZ</tt>, <tt>MSGTQL</tt>, <tt>MSGMNB</tt>,
-<tt>MSGMNI</tt> and <tt>MSGMAX</tt>. Under BSD, <tt>sysctl kern.ipc</tt>
+<code>MSGSEG</code>, <code>MSGSSZ</code>, <code>MSGTQL</code>, <code>MSGMNB</code>,
+<code>MSGMNI</code> and <code>MSGMAX</code>. Under BSD, <code>sysctl kern.ipc</code>
should tell you what you need to know and may allow you to change these
parameters.
</p>
@@ -1104,17 +1098,17 @@ won't go away when your process ends unless you explicitly remove it.
<p>In short, remember to clean up after yourself.</p>
-<h4>Consult Your Local <tt>man</tt> Pages</h4>
+<h4>Consult Your Local <code>man</code> Pages</h4>
<p>The sysv_ipc module is just a wrapper around your system's API. If your
-system's implementation has quirks, the <tt>man</tt> pages for <tt>semget, semctl, semop
-shmget, shmat, shmdt</tt> and <tt>shmctl</tt> will probably cover them.
+system's implementation has quirks, the <code>man</code> pages for <code>semget, semctl, semop
+shmget, shmat, shmdt</code> and <code>shmctl</code> will probably cover them.
</p>
<h4>Interesting Tools</h4>
<p>Many systems (although not some older versions of OS X) come
-with <tt>ipcs</tt> and <tt>ipcrm</tt>.
+with <code>ipcs</code> and <code>ipcrm</code>.
The former shows existing shared memory, semaphores and message queues on your system and
the latter allows you to remove them.
</p>
@@ -1152,7 +1146,7 @@ difficulty, user interest and so forth.
<ul>
<li>Update this documentation with a list of platforms that support semtimedop().</li>
- <li>Find a way to make <tt>SEMAPHORE_VALUE_MAX</tt> more accurate.</li>
+ <li>Find a way to make <code>SEMAPHORE_VALUE_MAX</code> more accurate.</li>
</ul>
<p>I don't plan on adding support for semaphore sets.</p>
diff --git a/VERSION b/VERSION
index 5d08204..9084fa2 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1 @@
-1.0.0
-
-
+1.1.0
diff --git a/common.c b/common.c
index 73f7e20..5c125fa 100644
--- a/common.c
+++ b/common.c
@@ -34,18 +34,6 @@ get_random_key(void) {
return (key_t)key;
}
-#if PY_MAJOR_VERSION < 3
-PyObject *
-py_int_or_long_from_ulong(unsigned long value) {
- // Python ints are guaranteed to accept up to LONG_MAX. Anything
- // larger needs to be a Python long.
- if (value > LONG_MAX)
- return PyLong_FromUnsignedLong(value);
- else
- return PyInt_FromLong(value);
-}
-#endif
-
int
convert_key_param(PyObject *py_key, void *converted_key) {
@@ -62,12 +50,6 @@ convert_key_param(PyObject *py_key, void *converted_key) {
rc = 1;
((NoneableKey *)converted_key)->is_none = 1;
}
-#if PY_MAJOR_VERSION < 3
- else if (PyInt_Check(py_key)) {
- rc = 1;
- key = PyInt_AsLong(py_key);
- }
-#endif
else if (PyLong_Check(py_key)) {
rc = 1;
key = PyLong_AsLong(py_key);
diff --git a/common.h b/common.h
index 3403199..4e3e433 100644
--- a/common.h
+++ b/common.h
@@ -103,83 +103,48 @@ Freebsd - l_int (int)
// I assume it is a long; see comment above.
// Some functions return (key_t)-1, so I guess this has to be a signed type.
// ref: http://www.opengroup.org/austin/interps/doc.tpl?gdid=6226
-#if PY_MAJOR_VERSION > 2
- #define KEY_T_TO_PY(key) PyLong_FromLong(key)
-#else
- #define KEY_T_TO_PY(key) PyInt_FromLong(key)
-#endif
+#define KEY_T_TO_PY(key) PyLong_FromLong(key)
+
// SUSv3 guarantees a uid_t to be an integer type. Some functions return
// (uid_t)-1, so I guess this has to be a signed type.
// ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
// ref: http://www.opengroup.org/onlinepubs/9699919799/functions/chown.html
-#if PY_MAJOR_VERSION > 2
- #define UID_T_TO_PY(uid) PyLong_FromLong(uid)
-#else
- #define UID_T_TO_PY(uid) PyInt_FromLong(uid)
-#endif
+#define UID_T_TO_PY(uid) PyLong_FromLong(uid)
// SUSv3 guarantees a gid_t to be an integer type. Some functions return
// (gid_t)-1, so I guess this has to be a signed type.
// ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
-#if PY_MAJOR_VERSION > 2
- #define GID_T_TO_PY(gid) PyLong_FromLong(gid)
-#else
- #define GID_T_TO_PY(gid) PyInt_FromLong(gid)
-#endif
+#define GID_T_TO_PY(gid) PyLong_FromLong(gid)
// I'm not sure what guarantees SUSv3 makes about a mode_t, but param 3 of
// shmget() is an int that contains flags in addition to the mode, so
// mode must be able to fit into an int.
// ref: http://www.opengroup.org/onlinepubs/009695399/functions/shmget.html
-#if PY_MAJOR_VERSION > 2
- #define MODE_T_TO_PY(mode) PyLong_FromLong(mode)
-#else
- #define MODE_T_TO_PY(mode) PyInt_FromLong(mode)
-#endif
+#define MODE_T_TO_PY(mode) PyLong_FromLong(mode)
// I'm not sure what guarantees SUSv3 makes about a time_t, but the times
// I deal with here are all guaranteed to be after 1 Jan 1970 which means
// they'll always be positive numbers. A ulong sounds appropriate to me,
// and Python agrees in posixmodule.c.
-#if PY_MAJOR_VERSION > 2
- #define TIME_T_TO_PY(time) PyLong_FromUnsignedLong(time)
-#else
- #define TIME_T_TO_PY(time) py_int_or_long_from_ulong(time)
-#endif
+#define TIME_T_TO_PY(time) PyLong_FromUnsignedLong(time)
// C89 guarantees a size_t to be unsigned and fit into a ulong or smaller.
-#if PY_MAJOR_VERSION > 2
- #define SIZE_T_TO_PY(size) PyLong_FromUnsignedLong(size)
-#else
- #define SIZE_T_TO_PY(size) py_int_or_long_from_ulong(size)
-#endif
+#define SIZE_T_TO_PY(size) PyLong_FromUnsignedLong(size)
// SUSv3 guarantees a pid_t to be a signed integer type. Some functions
// return (pid_t)-1 so I guess this has to be signed.
// ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/types.h.html#tag_13_67
-#if PY_MAJOR_VERSION > 2
- #define PID_T_TO_PY(pid) PyLong_FromLong(pid)
-#else
- #define PID_T_TO_PY(pid) PyInt_FromLong(pid)
-#endif
+#define PID_T_TO_PY(pid) PyLong_FromLong(pid)
// The SUS guarantees a msglen_t to be an unsigned integer type.
// Ditto: msgqnum_t.
// ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/msg.h.html
-#if PY_MAJOR_VERSION > 2
- #define MSGLEN_T_TO_PY(msglen) PyLong_FromUnsignedLong(msglen)
- #define MSGQNUM_T_TO_PY(msgqnum) PyLong_FromUnsignedLong(msgqnum)
-#else
- #define MSGLEN_T_TO_PY(msglen) py_int_or_long_from_ulong(msglen)
- #define MSGQNUM_T_TO_PY(msgqnum) py_int_or_long_from_ulong(msgqnum)
-#endif
+#define MSGLEN_T_TO_PY(msglen) PyLong_FromUnsignedLong(msglen)
+#define MSGQNUM_T_TO_PY(msgqnum) PyLong_FromUnsignedLong(msgqnum)
/* Utility functions */
key_t get_random_key(void);
int convert_key_param(PyObject *, void *);
-#if PY_MAJOR_VERSION < 3
-PyObject *py_int_or_long_from_ulong(unsigned long);
-#endif
/* Custom Exceptions/Errors */
extern PyObject *pBaseException;
diff --git a/debian/changelog b/debian/changelog
index c9ebe4b..41a48a1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+python-sysv-ipc (1.0.0+git20210117.3.d8b463a-1) UNRELEASED; urgency=low
+
+ * New upstream snapshot.
+ * New upstream snapshot.
+ * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 30 Dec 2022 16:59:39 -0000
+
python-sysv-ipc (1.0.0-2) unstable; urgency=medium
* Uploading to unstable.
diff --git a/demos/buffer_protocol/demo.py b/demos/buffer_protocol/demo.py
index fb42b16..04e1950 100644
--- a/demos/buffer_protocol/demo.py
+++ b/demos/buffer_protocol/demo.py
@@ -1,19 +1,11 @@
-import sys
-
import sysv_ipc
-IS_PY3 = (sys.version_info[0] == 3)
-to_chr = lambda c: chr(c) if IS_PY3 else c # noqa E731 (silence flake8)
-to_ord = lambda c: ord(c) if IS_PY3 else c # noqa E731 (silence flake8)
-
# Create a shared memory segment and write the (English) alphabet to the shared memory.
mem = sysv_ipc.SharedMemory(None, sysv_ipc.IPC_CREX, size=sysv_ipc.PAGE_SIZE)
ASCII_A = 0x61
alphabet = ''.join([chr(ASCII_A + i) for i in range(26)])
-if IS_PY3:
- alphabet = bytes(alphabet, 'ASCII')
-
+alphabet = bytes(alphabet, 'ASCII')
mem.write(alphabet)
# Create a bytearray from the SharedMemory.
@@ -39,16 +31,16 @@ mv = memoryview(mem)
# strides = (1, ), and is read/write.
# This shows that you can take slices of a memoryview
-assert([to_chr(c) for c in mv[3:6]] == ['d', 'e', 'f'])
+assert([chr(c) for c in mv[3:6]] == ['d', 'e', 'f'])
# This shows that you can write to the memoryview.
-mv[4] = to_ord('x')
+mv[4] = ord('x')
-assert([to_chr(c) for c in mv[3:6]] == ['d', 'x', 'f'])
+assert([chr(c) for c in mv[3:6]] == ['d', 'x', 'f'])
# Changes to the underlying segment are reflected in the memoryview
mem.write(b'xxx')
-assert([to_chr(c) for c in mv[:6]] == ['x', 'x', 'x', 'd', 'x', 'f'])
+assert([chr(c) for c in mv[:6]] == ['x', 'x', 'x', 'd', 'x', 'f'])
mem.detach()
mem.remove()
diff --git a/demos/message_queues/conclusion.py b/demos/message_queues/conclusion.py
index 3682c7e..7cbc476 100644
--- a/demos/message_queues/conclusion.py
+++ b/demos/message_queues/conclusion.py
@@ -1,5 +1,4 @@
# Python modules
-import sys
import hashlib
# 3rd party modules
@@ -8,8 +7,6 @@ import sysv_ipc
# Utils for this demo
import utils
-PY_MAJOR_VERSION = sys.version_info[0]
-
params = utils.read_params()
# Mrs. Premise has already created the message queue. I just need a handle to it.
@@ -33,8 +30,7 @@ for i in range(0, params["ITERATIONS"]):
utils.say("Received %s" % s)
if what_i_sent:
- if PY_MAJOR_VERSION > 2:
- what_i_sent = what_i_sent.encode()
+ what_i_sent = what_i_sent.encode()
try:
assert(s == hashlib.md5(what_i_sent).hexdigest())
except AssertionError:
diff --git a/demos/message_queues/premise.py b/demos/message_queues/premise.py
index 409e1d6..2e137ac 100644
--- a/demos/message_queues/premise.py
+++ b/demos/message_queues/premise.py
@@ -1,6 +1,5 @@
# Python modules
import time
-import sys
import hashlib
# 3rd party modules
@@ -9,8 +8,6 @@ import sysv_ipc
# Utils for this demo
import utils
-PY_MAJOR_VERSION = sys.version_info[0]
-
utils.say("Oooo 'ello, I'm Mrs. Premise!")
params = utils.read_params()
@@ -42,8 +39,7 @@ for i in range(0, params["ITERATIONS"]):
# What I read must be the md5 of what I wrote or something's
# gone wrong.
- if PY_MAJOR_VERSION > 2:
- what_i_sent = what_i_sent.encode()
+ what_i_sent = what_i_sent.encode()
try:
assert(s == hashlib.md5(what_i_sent).hexdigest())
except AssertionError:
diff --git a/demos/sem_and_shm/conclusion.py b/demos/sem_and_shm/conclusion.py
index 4b4fbb6..6a6002f 100755
--- a/demos/sem_and_shm/conclusion.py
+++ b/demos/sem_and_shm/conclusion.py
@@ -1,5 +1,4 @@
# Python modules
-import sys
import hashlib
# 3rd party modules
@@ -8,8 +7,6 @@ import sysv_ipc
# Utils for this demo
import utils
-PY_MAJOR_VERSION = sys.version_info[0]
-
utils.say("Oooo 'ello, I'm Mrs. Conclusion!")
params = utils.read_params()
@@ -43,15 +40,13 @@ for i in range(0, params["ITERATIONS"]):
s = utils.read_from_memory(memory)
if what_i_wrote:
- if PY_MAJOR_VERSION > 2:
- what_i_wrote = what_i_wrote.encode()
+ what_i_wrote = what_i_wrote.encode()
try:
assert(s == hashlib.md5(what_i_wrote).hexdigest())
except AssertionError:
raise AssertionError("Shared memory corruption after %d iterations." % i)
- if PY_MAJOR_VERSION > 2:
- s = s.encode()
+ s = s.encode()
what_i_wrote = hashlib.md5(s).hexdigest()
utils.write_to_memory(memory, what_i_wrote)
diff --git a/demos/sem_and_shm/params.txt b/demos/sem_and_shm/params.txt
old mode 100644
new mode 100755
index eff48bd..ce0e2a9
--- a/demos/sem_and_shm/params.txt
+++ b/demos/sem_and_shm/params.txt
@@ -2,14 +2,14 @@
# ITERATIONS is the number of times they'll talk to one another.
# LIVE_DANGEROUSLY is a Boolean (0 or 1); if set to 1 the programs
-# won't use the semaphore to coordinate access to the shared
+# won't use the semaphore to coordinate access to the shared
# memory. Corruption will likely result.
# KEY is the key to be used for the semaphore and shared memory.
# PERMISSIONS are in octal (note the leading 0).
# SHM_SIZE is the size of the shared memory segment in bytes.
ITERATIONS=1000
-LIVE_DANGEROUSLY=0
+LIVE_DANGEROUSLY=1
KEY=42
PERMISSIONS=0600
SHM_SIZE=4096
diff --git a/demos/sem_and_shm/premise.py b/demos/sem_and_shm/premise.py
index a486457..94e7cd3 100755
--- a/demos/sem_and_shm/premise.py
+++ b/demos/sem_and_shm/premise.py
@@ -1,6 +1,5 @@
# Python modules
import time
-import sys
import hashlib
# 3rd party modules
@@ -9,8 +8,6 @@ import sysv_ipc
# Utils for this demo
import utils
-PY_MAJOR_VERSION = sys.version_info[0]
-
utils.say("Oooo 'ello, I'm Mrs. Premise!")
params = utils.read_params()
@@ -63,8 +60,7 @@ for i in range(0, params["ITERATIONS"]):
s = utils.read_from_memory(memory)
# What I read must be the md5 of what I wrote or something's gone wrong.
- if PY_MAJOR_VERSION > 2:
- what_i_wrote = what_i_wrote.encode()
+ what_i_wrote = what_i_wrote.encode()
try:
assert(s == hashlib.md5(what_i_wrote).hexdigest())
@@ -72,8 +68,7 @@ for i in range(0, params["ITERATIONS"]):
raise AssertionError("Shared memory corruption after %d iterations." % i)
# MD5 the reply and write back to Mrs. Conclusion.
- if PY_MAJOR_VERSION > 2:
- s = s.encode()
+ s = s.encode()
what_i_wrote = hashlib.md5(s).hexdigest()
utils.write_to_memory(memory, what_i_wrote)
diff --git a/demos/sem_and_shm/utils.py b/demos/sem_and_shm/utils.py
index 112677c..855dce9 100644
--- a/demos/sem_and_shm/utils.py
+++ b/demos/sem_and_shm/utils.py
@@ -1,12 +1,7 @@
import time
import sys
-PY_MAJOR_VERSION = sys.version_info[0]
-
-if PY_MAJOR_VERSION > 2:
- NULL_CHAR = 0
-else:
- NULL_CHAR = '\0'
+NULL_CHAR = '\0'
def say(s):
@@ -19,17 +14,15 @@ def say(s):
def write_to_memory(memory, s):
say("writing %s " % s)
- s += '\0'
- if PY_MAJOR_VERSION > 2:
- s = s.encode()
+ s += NULL_CHAR
+ s = s.encode()
memory.write(s)
def read_from_memory(memory):
s = memory.read()
- if PY_MAJOR_VERSION > 2:
- s = s.decode()
- i = s.find('\0')
+ s = s.decode()
+ i = s.find(NULL_CHAR)
if i != -1:
s = s[:i]
say("read %s" % s)
diff --git a/extras/explore_max_semaphore_value.py b/extras/explore_max_semaphore_value.py
index 9d1641b..e057e74 100644
--- a/extras/explore_max_semaphore_value.py
+++ b/extras/explore_max_semaphore_value.py
@@ -11,4 +11,4 @@ for i in range(1, 100000):
print('{:05}: value is {}'.format(i, sem.value))
-sem.remove()
\ No newline at end of file
+sem.remove()
diff --git a/extras/ftok_experiment.py b/extras/ftok_experiment.py
index 39d2b75..9139b63 100644
--- a/extras/ftok_experiment.py
+++ b/extras/ftok_experiment.py
@@ -3,17 +3,11 @@ import sys
import os
import sysv_ipc
-# Python 2's raw_input() has become input() in Python 3.
-if sys.version_info[0] == 3:
- input_method = input
-else:
- input_method = raw_input # noqa - tell flake8 to chill
-
if len(sys.argv) == 2:
start_path = sys.argv[1]
else:
msg = "Start path? [Default = your home directory] "
- start_path = input_method(msg)
+ start_path = input(msg)
if not start_path:
start_path = "~"
@@ -23,6 +17,7 @@ start_path = os.path.abspath(start_path)
# For every filename in the tree, generate a key and associate the filename
# with that key via a dictionary.
+print(f"Scanning {start_path}...")
d = {}
nfilenames = 0
for path, dirnames, filenames in os.walk(start_path):
@@ -48,4 +43,4 @@ for key in d:
ndups += len(d[key])
print(key, d[key])
-print("Out of {0} unique filenames, I found {1} duplicate keys.".format(nfilenames, ndups))
+print(f"Out of {nfilenames} unique filenames, I found {ndups} duplicate keys.")
diff --git a/extras/memory_leak_tests.py b/extras/memory_leak_tests.py
index 73a8c05..3ffda4c 100644
--- a/extras/memory_leak_tests.py
+++ b/extras/memory_leak_tests.py
@@ -18,12 +18,10 @@ SKIP_MESSAGE_QUEUE_TESTS = False
# TEST_COUNT = 10
TEST_COUNT = 1024 * 100
-PY_MAJOR_VERSION = sys.version_info[0]
-
# ps output looks like this:
# RSZ VSZ
# 944 75964
-ps_output_regex = re.compile("""
+ps_output_regex = re.compile(r"""
^
\s* # whitespace before first heading
\S* # first heading (e.g. RSZ)
@@ -77,8 +75,7 @@ def get_memory_usage():
# RSZ VSZ
# 944 75964
- if PY_MAJOR_VERSION > 2:
- s = s.decode(sys.getfilesystemencoding())
+ s = s.decode(sys.getfilesystemencoding())
m = ps_output_regex.match(s)
@@ -467,26 +464,25 @@ else:
print_mem_after()
- if PY_MAJOR_VERSION > 2:
- print("Running memory read/write test with bytes...")
- print_mem_before()
+ print("Running memory read/write test with bytes...")
+ print_mem_before()
- mem = sysv_ipc.SharedMemory(42, sysv_ipc.IPC_CREX, size=sysv_ipc.PAGE_SIZE)
- alphabet = "abcdefghijklmnopqrstuvwxyz".encode()
+ mem = sysv_ipc.SharedMemory(42, sysv_ipc.IPC_CREX, size=sysv_ipc.PAGE_SIZE)
+ alphabet = "abcdefghijklmnopqrstuvwxyz".encode()
- s = alphabet
- length = len(s)
- for i in range(1, TEST_COUNT):
- # length = random.randint(1, sysv_ipc.PAGE_SIZE)
- # s = ''.join( [ random.choice(alphabet) for j in range(1, length + 1) ] )
- mem.write(s)
- assert(s == mem.read(length))
+ s = alphabet
+ length = len(s)
+ for i in range(1, TEST_COUNT):
+ # length = random.randint(1, sysv_ipc.PAGE_SIZE)
+ # s = ''.join( [ random.choice(alphabet) for j in range(1, length + 1) ] )
+ mem.write(s)
+ assert(s == mem.read(length))
- mem.detach()
+ mem.detach()
- mem.remove()
+ mem.remove()
- print_mem_after()
+ print_mem_after()
print("Running memory key read test...")
print_mem_before()
@@ -795,20 +791,19 @@ else:
print_mem_after()
- if PY_MAJOR_VERSION > 2:
- print("Running message queue send/receive test with bytes...")
- print_mem_before()
+ print("Running message queue send/receive test with bytes...")
+ print_mem_before()
- mq = sysv_ipc.MessageQueue(42, sysv_ipc.IPC_CREX)
+ mq = sysv_ipc.MessageQueue(42, sysv_ipc.IPC_CREX)
- for i in range(1, TEST_COUNT):
- s = random_string(15).encode()
- mq.send(s)
- assert(s == mq.receive()[0])
+ for i in range(1, TEST_COUNT):
+ s = random_string(15).encode()
+ mq.send(s)
+ assert(s == mq.receive()[0])
- mq.remove()
+ mq.remove()
- print_mem_after()
+ print_mem_after()
print("Running message queue key read test...")
print_mem_before()
diff --git a/history.html b/history.html
index b548b98..9714b18 100644
--- a/history.html
+++ b/history.html
@@ -1,16 +1,16 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE html>
-<html>
+<html lang='en'>
<head>
<meta charset="utf-8">
<meta name="author" content="Philip Semanchuk">
- <meta name="copyright" content="All contents © 2018 Philip Semanchuk">
+ <meta name="copyright" content="All contents © 2021 Philip Semanchuk">
<meta name="keywords" content="python sysv system v ipc semaphore shared memory message queue">
<title>The sysv_ipc Module for SysV IPC Under Python -- Version History</title>
- <style type="text/css">
+ <style>
li {
margin-top: .67em;
margin-bottom: .67em;
@@ -26,13 +26,30 @@
<a href="http://semanchuk.com/philip/sysv_ipc/">sysv_ipc module</a>.</p>
<ul>
- <li id="v1_0_0"><strong><span id="current">Current</span> – 1.0.0 (2 Feb 2018) –</strong>
+ <li id="v1_1_0"><strong><span id="current">Current</span> – 1.1.0 (17 Jan 2021) –</strong>
+ <ul>
+ <li>Drop support for Python 2, also for Python 3.4 and 3.5.</li>
+ <li><strong>Behavior change:</strong> <code>ftok()</code> now raises <code>OSError</code> if it fails so the particulars of the failure are visible to the caller. Thanks to James Williams for the suggestion. (Previously the function just returned -1 if it failed.)
+ </li>
+ </ul>
+ </li>
+
+ <li id="v1_0_1">1.0.1 (29 Nov 2019) –
+ <ul>
+ <li>Fix
+ <a href="https://github.com/osvenskan/sysv_ipc/issues/7">a memory leak bug in <code>SharedMemory.write()</code> that only occurred under Python 3</a>. Thanks to Andy for reporting!
+ </li>
+ <li>This will be the last version to support Python 2 which is pining for the fjords.</li>
+ </ul>
+ </li>
+
+ <li>1.0.0 (2 Feb 2018) –
<p>I'm bumping the version number to 1.0.0 because I now consider this feature complete.
That doesn't mean I won't add features, but I don't feel like I need to.
</p>
<ul>
- <li>Added support for Python <tt>memoryview</tt> and <tt>bytearray</tt> objects to be created from a <tt>SharedMemory</tt> instance.
+ <li>Added support for Python <code>memoryview</code> and <code>bytearray</code> objects to be created from a <code>SharedMemory</code> instance.
</li>
<li>Added support for building wheels.</li>
<li>Moved source code hosting to git and <a href='https://github.com/osvenskan/sysv_ipc'>GitHub</a>.</li>
@@ -45,36 +62,36 @@
<p>Version 0.7.0 is finally out now that this package is 7 years old...</p>
<ul>
- <li>Dropped compatibility with Python < 2.7.</li>
+ <li>Dropped compatibility with Python < 2.7.</li>
<li>Added unit tests with almost complete coverage.</li>
- <li>Fixed a doc bug for <tt>SharedMemory.write()</tt>. On an
+ <li>Fixed a doc bug for <code>SharedMemory.write()</code>. On an
attempt to write outside of the segment, the code raises
- <tt>ValueError</tt>. The documentation had incorrectly stated that
- <tt>write()</tt> would silently
+ <code>ValueError</code>. The documentation had incorrectly stated that
+ <code>write()</code> would silently
discard the data that overflowed the segment.
</li>
- <li>Fixed a code bug in <tt>SharedMemory.write()</tt> that
- incorrectly interpreted offsets > <tt>LONG_MAX</tt>.
+ <li>Fixed a code bug in <code>SharedMemory.write()</code> that
+ incorrectly interpreted offsets > <code>LONG_MAX</code>.
</li>
- <li>Fixed a code bug in <tt>SharedMemory.write()</tt> that
- didn’t always generate a <tt>ValueError</tt> for negative
+ <li>Fixed a code bug in <code>SharedMemory.write()</code> that
+ didn’t always generate a <code>ValueError</code> for negative
offsets.
</li>
- <li>Fixed a doc/code bug where <tt>SharedMemory.attach()</tt> was
+ <li>Fixed a doc/code bug where <code>SharedMemory.attach()</code> was
documented to accept keyword arguments but did not. Now it does.
</li>
<li>Fixed some header bugs that prevented the code from using
- <tt>PY_SSIZE_T_CLEAN</tt>. Thanks to Tilman Koschnick for
+ <code>PY_SSIZE_T_CLEAN</code>. Thanks to Tilman Koschnick for
bringing this to my attention.
</li>
- <li>Added doc to note that this module exposes <tt>SHM_RDONLY</tt>
+ <li>Added doc to note that this module exposes <code>SHM_RDONLY</code>
as a module-level constant.
</li>
</ul>
@@ -82,9 +99,9 @@
<li id="v0_6_8">0.6.8 (12 Sept 2014) –
<ul>
- <li>Fixed a bug in <tt>prober.py</tt> where prober would fail
+ <li>Fixed a bug in <code>prober.py</code> where prober would fail
on systems where Python's include file was not named
- <tt>pyconfig.h</tt>. (RHEL 6 is one such system.) Thanks to
+ <code>pyconfig.h</code>. (RHEL 6 is one such system.) Thanks to
Joshua Harlow for the bug report and patch.
</li>
@@ -134,10 +151,10 @@
<li id="v0_6_4">0.6.4 (19 Dec 2012) –
<ul>
- <li>Added a module-level <tt>attach()</tt> method based on a
+ <li>Added a module-level <code>attach()</code> method based on a
suggestion by Vladimír Včelák.
</li>
- <li>Added the <tt>ftok()</tt> method along with dire warnings about
+ <li>Added the <code>ftok()</code> method along with dire warnings about
its use.
</li>
</ul>
@@ -145,7 +162,7 @@
<li id="v0_6_3">0.6.3 (3 Oct 2010) –
<ul>
- <li>Fixed a segfault in <tt>write()</tt> that occurred any time
+ <li>Fixed a segfault in <code>write()</code> that occurred any time
an offset was passed. This was introduced in v0.6.0.
<i>Tack</i> to Johan Bernhardtson for the bug report.
</li>
@@ -164,7 +181,7 @@
<ul>
<li>Fixed a typo introduced in the previous version that caused
unpredictable behavior (usually a segfault) if a block flag
- was passed to <tt>MessageQueue.send()</tt>. <i>Obrigado</i>
+ was passed to <code>MessageQueue.send()</code>. <i>Obrigado</i>
to Álvaro Justen and Ronald Kaiser for the bug report and
patch.
</li>
@@ -187,8 +204,8 @@
(Daniel) for the bug report and patch.
</li>
<li>Fixed a bug where the module could have generated invalid
- keys on systems that typedef <tt>key_t</tt> as a
- <tt>short</tt>. I don't think such a system exists, though.
+ keys on systems that typedef <code>key_t</code> as a
+ <code>short</code>. I don't think such a system exists, though.
</li>
<li>Fixed a LICENSE file typo.</li>
<li>Added an RSS feed to this page.</li>
@@ -198,14 +215,14 @@
<li id="v0_5_1">0.5.1 (1 Dec 2009) –
<p>No code changes in this version.</p>
<ul>
- <li>Fixed the comment in <tt>sysv_ipc_module.c</tt> that
+ <li>Fixed the comment in <code>sysv_ipc_module.c</code> that
still referred to the GPL license.
</li>
- <li>Added the attributes <tt>__version</tt>, <tt>__author__</tt>,
- <tt>__license__</tt> and <tt>__copyright__</tt>.
+ <li>Added the attributes <code>__version</code>, <code>__author__</code>,
+ <code>__license__</code> and <code>__copyright__</code>.
</li>
- <li>Removed <tt>file()</tt> from <tt>setup.py</tt> in favor
- of <tt>open()</tt>.
+ <li>Removed <code>file()</code> from <code>setup.py</code> in favor
+ of <code>open()</code>.
</li>
</ul>
</li>
@@ -230,17 +247,17 @@
<li>Changed status to beta.</li>
<li>Added automatic generation of keys.</li>
<li>Added a message queue demo.</li>
- <li>Added <tt>str()</tt> and <tt>repr()</tt> support to all
+ <li>Added <code>str()</code> and <code>repr()</code> support to all
objects.</li>
- <li>Fixed a bug in <tt>SharedMemory.write()</tt> that could cause
+ <li>Fixed a bug in <code>SharedMemory.write()</code> that could cause
a spurious error of "Attempt to write past end of memory
segment". This bug only occurred on platforms using
- different sizes for <tt>long</tt> and <tt>int</tt>, or
- <tt>long</tt> and <tt>py_size_t</tt>
+ different sizes for <code>long</code> and <code>int</code>, or
+ <code>long</code> and <code>py_size_t</code>
(depending on Python version). <em>Tack</em> to Jesper
for debug help.
</li>
- <li>Plugged a memory leak in <tt>MessageQueue.receive()</tt>.</li>
+ <li>Plugged a memory leak in <code>MessageQueue.receive()</code>.</li>
<li>Added a VERSION attribute to the module.</li>
</ul>
</li>
@@ -248,14 +265,14 @@
<li id="v0_4">0.4 (28 Jan 2009) –
<ul>
<li>Added message queues.</li>
- <li>Fixed a bug where the <tt>key</tt> attribute of SharedMemory objects
+ <li>Fixed a bug where the <code>key</code> attribute of SharedMemory objects
returned garbage.
</li>
<li>Fixed a bug where keys > INT_MAX would get truncated on
platforms where longs are bigger than ints.
</li>
<li>Provided decent inline documentation for object attributes
- (available via the <tt>help()</tt> command).
+ (available via the <code>help()</code> command).
</li>
<li>Rearranged the code which was suffering growing pains.</li>
</ul>
@@ -267,15 +284,15 @@
semaphore timeouts, and many small fixes.
</p>
- <p>A semaphore's <tt>.block</tt> flag now consistently trumps the
- timeout. When <tt>False</tt>, the timeout is irrelevant -- calls
+ <p>A semaphore's <code>.block</code> flag now consistently trumps the
+ timeout. When <code>False</code>, the timeout is irrelevant -- calls
will never block. In prior versions, the flag was ignored
when the timeout was non-zero.
</p>
- <p>Also, on platforms (such as OS X) where <tt>semtimedop()</tt> is
- not supported, all timeouts are now treated as <tt>None</tt>.
- In other words, when <tt>.block</tt> is True, all calls
+ <p>Also, on platforms (such as OS X) where <code>semtimedop()</code> is
+ not supported, all timeouts are now treated as <code>None</code>.
+ In other words, when <code>.block</code> is True, all calls
wait as long as necessary.
</p>
@@ -295,36 +312,36 @@
<li>Got rid of OS X compile warnings.</li>
<li>Fixed many instances where I was making potentially lossy
conversions between Python values and Unix-specific
- types like <tt>key_t</tt>, <tt>pid_t</tt>, etc.
+ types like <code>key_t</code>, <code>pid_t</code>, etc.
</li>
- <li>Fixed a bug in the SharedMemory <tt>attach()</tt> function
+ <li>Fixed a bug in the SharedMemory <code>attach()</code> function
that would set an error string but not return an error
- value if the passed address was not <tt>None</tt> or a long.
+ value if the passed address was not <code>None</code> or a long.
</li>
<li>Simplified the code a little.</li>
- <li>Restricted the semaphore <tt>acquire()</tt> and
- <tt>release()</tt> delta to be between SHORT_MIN and
+ <li>Restricted the semaphore <code>acquire()</code> and
+ <code>release()</code> delta to be between SHORT_MIN and
SHORT_MAX since
<a href="http://opengroup.org/onlinepubs/007908775/xsh/semop.html">it
is a short in the SUSv2 spec</a>.
</li>
- <li>Fixed a bug where calling <tt>acquire()</tt> or
- <tt>release()</tt> with a delta of <tt>0</tt> would call
- <tt>.Z()</tt> instead.
+ <li>Fixed a bug where calling <code>acquire()</code> or
+ <code>release()</code> with a delta of <code>0</code> would call
+ <code>.Z()</code> instead.
</li>
- <li>Disallowed byte counts ≤ <tt>0</tt> in
- <tt>SharedMemory.read()</tt>
+ <li>Disallowed byte counts ≤ <code>0</code> in
+ <code>SharedMemory.read()</code>
</li>
- <li>Fixed a bug in the <tt>SharedMemory</tt> init code that
+ <li>Fixed a bug in the <code>SharedMemory</code> init code that
could, under vanishingly rare circumstances, return failure
without setting the error code.
</li>
- <li>Removed some dead code relating to the <tt>.seq</tt> member
- of the <tt>sem_perm</tt> and <tt>shm_perm</tt> structs.
+ <li>Removed some dead code relating to the <code>.seq</code> member
+ of the <code>sem_perm</code> and <code>shm_perm</code> structs.
</li>
- <li>Stopped accessing the non-standard <tt>key</tt>
- (a.k.a. <tt>_key</tt> and <tt>__key</tt>) element of the
- <tt>ipc_perm</tt> struct.
+ <li>Stopped accessing the non-standard <code>key</code>
+ (a.k.a. <code>_key</code> and <code>__key</code>) element of the
+ <code>ipc_perm</code> struct.
</li>
<li>Added code to ensure the module doesn't try to create
a string that's larger than Python permits when reading
@@ -336,15 +353,15 @@
<li>0.2.1 (3 Jan 2009) –
<ul>
<li>Fixed a bug that prevented the module-specific
- errors (<tt>ExistentialError</tt>, etc.) from
+ errors (<code>ExistentialError</code>, etc.) from
being visible in the module.
</li>
<li>Fixed a bug that re-initialized shared memory with
- the init character when only <tt>IPC_CREAT</tt> was specified
+ the init character when only <code>IPC_CREAT</code> was specified
and an existing segment was opened.
</li>
<li>Fixed a bug that always defaulted the size of a shared
- memory segment to <tt>PAGE_SIZE</tt>. Updated code and
+ memory segment to <code>PAGE_SIZE</code>. Updated code and
documentation to use intelligent defaults. <em>Tack</em> to
Jesper for the bug report.
</li>
@@ -359,7 +376,7 @@
Lots of small fixes.
<ul>
- <li>Fixed a bug where calling <tt>shm.remove()</tt> on shared
+ <li>Fixed a bug where calling <code>shm.remove()</code> on shared
memory that was already removed would cause a SystemError.
(I wasn't setting the Python error before returning.)
</li>
@@ -372,14 +389,14 @@
of a new, read-only semaphore to fail.
</li>
- <li>Added the constant <tt>IPC_CREX</tt>.</li>
+ <li>Added the constant <code>IPC_CREX</code>.</li>
- <li>Renamed (sorry) <tt>MAX_KEY</tt> to <tt>KEY_MAX</tt> and
- <tt>MAX_SEMAPHORE_VALUE</tt> to <tt>SEMAPHORE_VALUE_MAX</tt>
+ <li>Renamed (sorry) <code>MAX_KEY</code> to <code>KEY_MAX</code> and
+ <code>MAX_SEMAPHORE_VALUE</code> to <code>SEMAPHORE_VALUE_MAX</code>
to be consistent with the C naming convention in limits.h.
</li>
- <li>Hardcoded <tt>SEMAPHORE_VALUE_MAX</tt> to 32767 until I can
+ <li>Hardcoded <code>SEMAPHORE_VALUE_MAX</code> to 32767 until I can
find a reliable way to determine it at install time.
</li>
diff --git a/keys.c b/keys.c
deleted file mode 100644
index 12f44dd..0000000
--- a/keys.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-
-int main() {
- int i;
- int key;
-
-
- for (i = 0; i < 10000000; i++) {
- // ref: http://www.c-faq.com/lib/randrange.html
- key = ((int)((double)rand() / ((double)RAND_MAX + 1) * INT_MAX)) + 1;
- printf("%d\n", key);
- }
-
-
-
- return 1;
-}
\ No newline at end of file
diff --git a/memory.c b/memory.c
index f6242d5..0d05506 100644
--- a/memory.c
+++ b/memory.c
@@ -9,20 +9,12 @@
/****************** Internal use only **********************/
PyObject *
shm_str(SharedMemory *self) {
-#if PY_MAJOR_VERSION > 2
- return PyUnicode_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#else
- return PyString_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#endif
+ return PyUnicode_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
}
PyObject *
shm_repr(SharedMemory *self) {
-#if PY_MAJOR_VERSION > 2
return PyUnicode_FromFormat("sysv_ipc.SharedMemory(%ld)", (long)self->key);
-#else
- return PyString_FromFormat("sysv_ipc.SharedMemory(%ld)", (long)self->key);
-#endif
}
PyObject *
@@ -159,11 +151,7 @@ shm_get_value(int shared_memory_id, enum GET_SET_IDENTIFIERS field) {
case SVIFP_SHM_NUMBER_ATTACHED:
// shm_nattch is unsigned
// ref: http://www.opengroup.org/onlinepubs/007908799/xsh/sysshm.h.html
-#if PY_MAJOR_VERSION > 2
py_value = PyLong_FromUnsignedLong(shm_info.shm_nattch);
-#else
- py_value = py_int_or_long_from_ulong(shm_info.shm_nattch);
-#endif
break;
case SVIFP_IPC_PERM_UID:
@@ -286,11 +274,7 @@ shm_get_buffer(SharedMemory *self, Py_buffer *view, int flags)
return -1;
}
else {
-#if PY_MAJOR_VERSION > 2
size = PyLong_AsSsize_t(py_size);
-#else
- size = PyInt_AsSsize_t(py_size);
-#endif
Py_DECREF(py_size);
return PyBuffer_FillInfo(view,
(PyObject *)self,
@@ -443,11 +427,7 @@ SharedMemory_init(SharedMemory *self, PyObject *args, PyObject *keywords) {
if (!py_size)
goto error_return;
else {
-#if PY_MAJOR_VERSION > 2
size = PyLong_AsUnsignedLongMask(py_size);
-#else
- size = PyInt_AsUnsignedLongMask(py_size);
-#endif
DPRINTF("memsetting address %p to %lu bytes of ASCII 0x%x (%c)\n", \
self->address, size, (int)init_character, init_character);
@@ -546,11 +526,7 @@ SharedMemory_read(SharedMemory *self, PyObject *args, PyObject *keywords) {
}
if ( (py_size = shm_get_value(self->id, SVIFP_SHM_SIZE)) ) {
-#if PY_MAJOR_VERSION > 2
size = PyLong_AsUnsignedLongMask(py_size);
-#else
- size = PyInt_AsUnsignedLongMask(py_size);
-#endif
Py_DECREF(py_size);
}
else
@@ -590,12 +566,7 @@ SharedMemory_read(SharedMemory *self, PyObject *args, PyObject *keywords) {
}
}
-
-#if PY_MAJOR_VERSION > 2
return PyBytes_FromStringAndSize(self->address + offset, byte_count);
-#else
- return PyString_FromStringAndSize(self->address + offset, byte_count);
-#endif
error_return:
return NULL;
@@ -617,44 +588,26 @@ SharedMemory_write(SharedMemory *self, PyObject *args, PyObject *kw) {
unsigned long size;
PyObject *py_size;
char *keyword_list[ ] = {"s", "offset", NULL};
-#if PY_MAJOR_VERSION > 2
static char args_format[] = "s*|k";
Py_buffer data;
-#else
- static char args_format[] = "s#|k";
- typedef struct {
- const char *buf;
- long len;
- } MyBuffer;
- MyBuffer data;
- data.len = 0;
-#endif
-
- if (self->read_only) {
- PyErr_SetString(PyExc_OSError, "Write attempt on read-only memory segment");
- goto error_return;
- }
if (!PyArg_ParseTupleAndKeywords(args, kw, args_format, keyword_list,
-#if PY_MAJOR_VERSION > 2
&data,
-#else
- &(data.buf), &(data.len),
-#endif
&offset))
goto error_return;
+ if (self->read_only) {
+ PyErr_SetString(PyExc_OSError, "Write attempt on read-only memory segment");
+ goto error_return;
+ }
+
if (self->address == NULL) {
PyErr_SetString(pNotAttachedException, "Write attempt on unattached memory segment");
goto error_return;
}
if ( (py_size = shm_get_value(self->id, SVIFP_SHM_SIZE)) ) {
-#if PY_MAJOR_VERSION > 2
size = PyLong_AsUnsignedLongMask(py_size);
-#else
- size = PyInt_AsUnsignedLongMask(py_size);
-#endif
Py_DECREF(py_size);
}
else
@@ -673,9 +626,12 @@ SharedMemory_write(SharedMemory *self, PyObject *args, PyObject *kw) {
memcpy((self->address + offset), data.buf, data.len);
+ PyBuffer_Release(&data);
+
Py_RETURN_NONE;
error_return:
+ PyBuffer_Release(&data);
return NULL;
}
@@ -762,21 +718,13 @@ int
shm_set_uid(SharedMemory *self, PyObject *py_value) {
union ipc_perm_value new_value;
-#if PY_MAJOR_VERSION > 2
if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
{
PyErr_SetString(PyExc_TypeError, "Attribute 'uid' must be an integer");
goto error_return;
}
-#if PY_MAJOR_VERSION > 2
new_value.uid = PyLong_AsLong(py_value);
-#else
- new_value.uid = PyInt_AsLong(py_value);
-#endif
if (((uid_t)-1 == new_value.uid) && PyErr_Occurred()) {
// no idea what could have gone wrong -- punt it up to the caller
@@ -799,21 +747,13 @@ int
shm_set_gid(SharedMemory *self, PyObject *py_value) {
union ipc_perm_value new_value;
-#if PY_MAJOR_VERSION > 2
if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
{
PyErr_Format(PyExc_TypeError, "attribute 'gid' must be an integer");
goto error_return;
}
-#if PY_MAJOR_VERSION > 2
new_value.gid = PyLong_AsLong(py_value);
-#else
- new_value.gid = PyInt_AsLong(py_value);
-#endif
if (((gid_t)-1 == new_value.gid) && PyErr_Occurred()) {
// no idea what could have gone wrong -- punt it up to the caller
@@ -830,21 +770,13 @@ int
shm_set_mode(SharedMemory *self, PyObject *py_value) {
union ipc_perm_value new_value;
-#if PY_MAJOR_VERSION > 2
if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
{
PyErr_Format(PyExc_TypeError, "attribute 'mode' must be an integer");
goto error_return;
}
-#if PY_MAJOR_VERSION > 2
new_value.mode = PyLong_AsLong(py_value);
-#else
- new_value.mode = PyInt_AsLong(py_value);
-#endif
if (((mode_t)-1 == new_value.mode) && PyErr_Occurred()) {
// no idea what could have gone wrong -- punt it up to the caller
diff --git a/mq.c b/mq.c
index 4ad4d37..da50c2a 100644
--- a/mq.c
+++ b/mq.c
@@ -8,21 +8,13 @@
PyObject *
mq_str(MessageQueue *self) {
-#if PY_MAJOR_VERSION > 2
return PyUnicode_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#else
- return PyString_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#endif
}
PyObject *
mq_repr(MessageQueue *self) {
-#if PY_MAJOR_VERSION > 2
return PyUnicode_FromFormat("sysv_ipc.MessageQueue(%ld)", (long)self->key);
-#else
- return PyString_FromFormat("sysv_ipc.MessageQueue(%ld)", (long)self->key);
-#endif
}
@@ -119,12 +111,7 @@ int
set_a_value(int id, enum GET_SET_IDENTIFIERS field, PyObject *py_value) {
struct msqid_ds mq_info;
-#if PY_MAJOR_VERSION > 2
- if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
- {
+ if (!PyLong_Check(py_value)) {
PyErr_Format(PyExc_TypeError, "The attribute must be an integer");
goto error_return;
}
@@ -156,37 +143,21 @@ set_a_value(int id, enum GET_SET_IDENTIFIERS field, PyObject *py_value) {
switch (field) {
case SVIFP_IPC_PERM_UID:
-#if PY_MAJOR_VERSION > 2
mq_info.msg_perm.uid = PyLong_AsLong(py_value);
-#else
- mq_info.msg_perm.uid = PyInt_AsLong(py_value);
-#endif
break;
case SVIFP_IPC_PERM_GID:
-#if PY_MAJOR_VERSION > 2
mq_info.msg_perm.gid = PyLong_AsLong(py_value);
-#else
- mq_info.msg_perm.gid = PyInt_AsLong(py_value);
-#endif
break;
case SVIFP_IPC_PERM_MODE:
-#if PY_MAJOR_VERSION > 2
mq_info.msg_perm.mode = PyLong_AsLong(py_value);
-#else
- mq_info.msg_perm.mode = PyInt_AsLong(py_value);
-#endif
break;
case SVIFP_MQ_QUEUE_BYTES_MAX:
// A msglen_t is unsigned.
// ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/msg.h.html
-#if PY_MAJOR_VERSION > 2
mq_info.msg_qbytes = PyLong_AsUnsignedLongMask(py_value);
-#else
- mq_info.msg_qbytes = PyInt_AsUnsignedLongMask(py_value);
-#endif
break;
default:
@@ -466,18 +437,8 @@ MessageQueue_send(MessageQueue *self, PyObject *args, PyObject *keywords) {
py_ssize_t. Therefore I *must* initialize it to 0 so that whatever
Python doesn't write to is zeroed out.
*/
-#if PY_MAJOR_VERSION > 2
static char args_format[] = "s*|Oi";
Py_buffer user_msg;
-#else
- static char args_format[] = "s#|Oi";
- typedef struct {
- char *buf;
- long len;
- } MyBuffer;
- MyBuffer user_msg;
- user_msg.len = 0;
-#endif
PyObject *py_block = NULL;
int flags = 0;
int type = 1;
@@ -487,12 +448,7 @@ MessageQueue_send(MessageQueue *self, PyObject *args, PyObject *keywords) {
// send(message, [block = True, [type = 1]])
if (!PyArg_ParseTupleAndKeywords(args, keywords, args_format, keyword_list,
-#if PY_MAJOR_VERSION > 2
- &user_msg,
-#else
- &(user_msg.buf), &(user_msg.len),
-#endif
- &py_block, &type))
+ &user_msg, &py_block, &type))
goto error_return;
if (type <= 0) {
@@ -560,19 +516,12 @@ MessageQueue_send(MessageQueue *self, PyObject *args, PyObject *keywords) {
goto error_return;
}
-
-#if PY_MAJOR_VERSION > 2
PyBuffer_Release(&user_msg);
-#endif
-
free(p_msg);
-
Py_RETURN_NONE;
error_return:
-#if PY_MAJOR_VERSION > 2
PyBuffer_Release(&user_msg);
-#endif
free(p_msg);
return NULL;
}
@@ -647,13 +596,8 @@ MessageQueue_receive(MessageQueue *self, PyObject *args, PyObject *keywords) {
}
py_return_tuple = Py_BuildValue("NN",
-#if PY_MAJOR_VERSION > 2
PyBytes_FromStringAndSize(p_msg->message, rc),
PyLong_FromLong(p_msg->type)
-#else
- PyString_FromStringAndSize(p_msg->message, rc),
- PyInt_FromLong(p_msg->type)
-#endif
);
free(p_msg);
@@ -670,4 +614,3 @@ PyObject *
MessageQueue_remove(MessageQueue *self) {
return mq_remove(self->id);
}
-
diff --git a/post_dist.py b/post_dist.py
deleted file mode 100755
index 9607eb2..0000000
--- a/post_dist.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-
-# Python imports
-import time
-import hashlib
-import shutil
-import os
-
-RSS_TIMESTAMP_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
-
-VERSION = open("VERSION").read().strip()
-
-# Make a copy of the tarball for posterity
-tarball_name = "sysv_ipc-%s.tar.gz" % VERSION
-shutil.copyfile(os.path.join("dist", tarball_name),
- os.path.join("releases", tarball_name))
-
-tarball_name = "releases/sysv_ipc-%s.tar.gz" % VERSION
-md5_name = "releases/sysv_ipc-%s.md5.txt" % VERSION
-sha1_name = "releases/sysv_ipc-%s.sha1.txt" % VERSION
-
-# Generate hashes of the tarball
-tarball_content = open(tarball_name, 'rb').read()
-for hash_function_name in ('md5', 'sha1', 'sha256'):
- hash_function = getattr(hashlib, hash_function_name)
- hash_value = hash_function(tarball_content).hexdigest()
-
- hash_filename = "releases/sysv_ipc-{}.{}.txt".format(VERSION, hash_function_name)
-
- open(hash_filename, "wb").write(hash_value.encode('ascii'))
- print(hash_function_name + " = " + hash_value)
-
-# Print an RSS item suitable for pasting into rss.xml
-timestamp = time.strftime(RSS_TIMESTAMP_FORMAT, time.gmtime())
-
-print("""
-
- <item>
- <guid isPermaLink="false">%s</guid>
- <title>sysv_ipc %s Released</title>
- <pubDate>%s</pubDate>
- <link>http://semanchuk.com/philip/sysv_ipc/</link>
- <description>Version %s of sysv_ipc has been released.
- </description>
- </item>
-
-""" % (VERSION, VERSION, timestamp, VERSION))
-
-print("Don't forget this:\ngit tag rel" + VERSION)
diff --git a/prober.py b/prober.py
index 93cbd23..9bb3f40 100644
--- a/prober.py
+++ b/prober.py
@@ -131,9 +131,10 @@ def probe():
"PAGE_SIZE",
]
- version = open("VERSION").read().strip()
+ with open("VERSION") as f:
+ version = f.read().strip()
- d["SYSV_IPC_VERSION"] = '"%s"' % version
+ d["SYSV_IPC_VERSION"] = f'"{version}"'
d["PAGE_SIZE"] = probe_page_size()
if sniff_semtimedop():
d["SEMTIMEDOP_EXISTS"] = ""
diff --git a/semaphore.c b/semaphore.c
index 6e0e9f2..3159f5b 100644
--- a/semaphore.c
+++ b/semaphore.c
@@ -32,6 +32,9 @@ union semun {
int val; /* used for SETVAL only */
struct semid_ds *buf; /* for IPC_STAT and IPC_SET */
unsigned short *array; /* used for GETALL and SETALL */
+#ifdef __linux__
+ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
+#endif
};
#endif
@@ -55,12 +58,6 @@ convert_timeout(PyObject *py_timeout, void *converted_timeout) {
rc = 1;
simple_timeout = PyFloat_AsDouble(py_timeout);
}
-#if PY_MAJOR_VERSION < 3
- else if (PyInt_Check(py_timeout)) {
- rc = 1;
- simple_timeout = (double)PyInt_AsLong(py_timeout);
- }
-#endif
else if (PyLong_Check(py_timeout)) {
rc = 1;
simple_timeout = (double)PyLong_AsLong(py_timeout);
@@ -95,21 +92,13 @@ convert_timeout(PyObject *py_timeout, void *converted_timeout) {
PyObject *
sem_str(Semaphore *self) {
-#if PY_MAJOR_VERSION > 2
return PyUnicode_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#else
- return PyString_FromFormat("Key=%ld, id=%d", (long)self->key, self->id);
-#endif
}
PyObject *
sem_repr(Semaphore *self) {
-#if PY_MAJOR_VERSION > 2
return PyUnicode_FromFormat("sysv_ipc.Semaphore(%ld)", (long)self->key);
-#else
- return PyString_FromFormat("sysv_ipc.Semaphore(%ld)", (long)self->key);
-#endif
}
@@ -288,11 +277,7 @@ sem_get_semctl_value(int semaphore_id, int cmd) {
goto error_return;
}
-#if PY_MAJOR_VERSION > 2
return PyLong_FromLong(rc);
-#else
- return PyInt_FromLong(rc);
-#endif
error_return:
return NULL;
@@ -360,11 +345,7 @@ sem_set_ipc_perm_value(int id, enum GET_SET_IDENTIFIERS field, PyObject *py_valu
arg.buf = &sem_info;
-#if PY_MAJOR_VERSION > 2
if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
{
PyErr_Format(PyExc_TypeError, "The attribute must be an integer");
goto error_return;
@@ -388,27 +369,15 @@ sem_set_ipc_perm_value(int id, enum GET_SET_IDENTIFIERS field, PyObject *py_valu
// cast. If the user passes a value that's too big, tough cookies.
switch (field) {
case SVIFP_IPC_PERM_UID:
-#if PY_MAJOR_VERSION > 2
sem_info.sem_perm.uid = (uid_t)PyLong_AsLong(py_value);
-#else
- sem_info.sem_perm.uid = (uid_t)PyInt_AsLong(py_value);
-#endif
break;
case SVIFP_IPC_PERM_GID:
-#if PY_MAJOR_VERSION > 2
sem_info.sem_perm.gid = (gid_t)PyLong_AsLong(py_value);
-#else
- sem_info.sem_perm.gid = (gid_t)PyInt_AsLong(py_value);
-#endif
break;
case SVIFP_IPC_PERM_MODE:
-#if PY_MAJOR_VERSION > 2
sem_info.sem_perm.mode = (mode_t)PyLong_AsLong(py_value);
-#else
- sem_info.sem_perm.mode = (mode_t)PyInt_AsLong(py_value);
-#endif
break;
default:
@@ -621,21 +590,13 @@ sem_set_value(Semaphore *self, PyObject *py_value)
union semun arg;
long value;
-#if PY_MAJOR_VERSION > 2
if (!PyLong_Check(py_value))
-#else
- if (!PyInt_Check(py_value))
-#endif
{
PyErr_Format(PyExc_TypeError, "Attribute 'value' must be an integer");
goto error_return;
}
-#if PY_MAJOR_VERSION > 2
value = PyLong_AsLong(py_value);
-#else
- value = PyInt_AsLong(py_value);
-#endif
DPRINTF("C value is %ld\n", value);
diff --git a/setup.cfg b/setup.cfg
index 9d58686..8b278d5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,7 @@
[flake8]
max-line-length = 100
+[egg_info]
+tag_build =
+tag_date = 0
+
diff --git a/setup.py b/setup.py
index 813fe15..3258275 100644
--- a/setup.py
+++ b/setup.py
@@ -32,7 +32,6 @@ classifiers = ["Development Status :: 5 - Production/Stable",
"Operating System :: POSIX",
"Operating System :: Unix",
"Programming Language :: Python",
- "Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Topic :: Utilities"]
license = "http://creativecommons.org/licenses/BSD/"
diff --git a/sysv_ipc.egg-info/PKG-INFO b/sysv_ipc.egg-info/PKG-INFO
new file mode 100644
index 0000000..c3a49d4
--- /dev/null
+++ b/sysv_ipc.egg-info/PKG-INFO
@@ -0,0 +1,37 @@
+Metadata-Version: 2.1
+Name: sysv-ipc
+Version: 1.1.0
+Summary: System V IPC primitives (semaphores, shared memory and message queues) for Python
+Home-page: http://semanchuk.com/philip/sysv_ipc/
+Download-URL: http://semanchuk.com/philip/sysv_ipc/sysv_ipc-1.1.0.tar.gz
+Author: Philip Semanchuk
+Author-email: philip@semanchuk.com
+Maintainer: Philip Semanchuk
+License: http://creativecommons.org/licenses/BSD/
+Keywords: sysv ipc inter-process communication semaphore shared memory shm message queue
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: POSIX :: SunOS/Solaris
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Unix
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Utilities
+License-File: LICENSE
+
+Sysv_ipc gives Python programs access to System V semaphores, shared memory
+and message queues. Most (all?) Unixes (including OS X) support System V IPC.
+Windows+Cygwin 1.7 might also work.
+
+Sample code is included.
+
+sysv_ipc is free software (free as in speech and free as in beer) released
+under a 3-clause BSD license. Complete licensing information is available in
+the LICENSE file.
+
+You might also be interested in the similar POSIX IPC module at:
+http://semanchuk.com/philip/posix_ipc/
diff --git a/sysv_ipc.egg-info/SOURCES.txt b/sysv_ipc.egg-info/SOURCES.txt
new file mode 100644
index 0000000..7d0b0d0
--- /dev/null
+++ b/sysv_ipc.egg-info/SOURCES.txt
@@ -0,0 +1,62 @@
+INSTALL
+LICENSE
+MANIFEST.in
+README
+ReadMe.html
+VERSION
+common.c
+common.h
+history.html
+memory.c
+memory.h
+mq.c
+mq.h
+prober.py
+semaphore.c
+semaphore.h
+setup.cfg
+setup.py
+sysv_ipc_module.c
+demos/buffer_protocol/ReadMe.md
+demos/buffer_protocol/demo.py
+demos/message_queues/ReadMe.txt
+demos/message_queues/SampleIpcConversation.png
+demos/message_queues/cleanup.py
+demos/message_queues/conclusion.py
+demos/message_queues/params.txt
+demos/message_queues/premise.py
+demos/message_queues/utils.py
+demos/sem_and_shm/ReadMe.txt
+demos/sem_and_shm/SampleIpcConversation.png
+demos/sem_and_shm/cleanup.py
+demos/sem_and_shm/conclusion.c
+demos/sem_and_shm/conclusion.py
+demos/sem_and_shm/make_all.sh
+demos/sem_and_shm/md5.c
+demos/sem_and_shm/md5.h
+demos/sem_and_shm/params.txt
+demos/sem_and_shm/premise.c
+demos/sem_and_shm/premise.py
+demos/sem_and_shm/utils.c
+demos/sem_and_shm/utils.h
+demos/sem_and_shm/utils.py
+demos/semaphore_context_manager/ReadMe.txt
+demos/semaphore_context_manager/child.py
+demos/semaphore_context_manager/parent.py
+extras/explore_max_semaphore_value.py
+extras/ftok_experiment.py
+extras/memory_leak_tests.py
+extras/memory_limit_test.py
+prober/probe_page_size.c
+prober/semtimedop_test.c
+prober/sniff_union_semun_defined.c
+sysv_ipc.egg-info/PKG-INFO
+sysv_ipc.egg-info/SOURCES.txt
+sysv_ipc.egg-info/dependency_links.txt
+sysv_ipc.egg-info/top_level.txt
+tests/__init__.py
+tests/base.py
+tests/test_memory.py
+tests/test_message_queues.py
+tests/test_module.py
+tests/test_semaphores.py
\ No newline at end of file
diff --git a/sysv_ipc.egg-info/dependency_links.txt b/sysv_ipc.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/sysv_ipc.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/sysv_ipc.egg-info/top_level.txt b/sysv_ipc.egg-info/top_level.txt
new file mode 100644
index 0000000..c4bbcda
--- /dev/null
+++ b/sysv_ipc.egg-info/top_level.txt
@@ -0,0 +1 @@
+sysv_ipc
diff --git a/sysv_ipc_module.c b/sysv_ipc_module.c
index e1fc3d9..1cce2cc 100644
--- a/sysv_ipc_module.c
+++ b/sysv_ipc_module.c
@@ -2,7 +2,7 @@
sysv_ipc - A Python module for accessing System V semaphores, shared memory
and message queues.
-Copyright (c) 2018, Philip Semanchuk
+Copyright (c) 2021, Philip Semanchuk
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -136,6 +136,11 @@ sysv_ipc_ftok(PyObject *self, PyObject *args, PyObject *keywords) {
DPRINTF("path=%s, id=%d, rc=%ld\n", path, id, (long)rc);
+ if (rc == (key_t)-1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error_return;
+ }
+
return Py_BuildValue("i", rc);
error_return:
@@ -506,12 +511,6 @@ https://stackoverflow.com/questions/19223721/definition-of-pybufferprocs-in-pyth
Fortunately all the extra fields in the Python 2 version of the struct can just be NULL.
*/
PyBufferProcs SharedMemory_as_buffer = {
-#if PY_MAJOR_VERSION == 2
- (readbufferproc)NULL,
- (writebufferproc)NULL,
- (segcountproc)NULL,
- (charbufferproc)NULL,
-#endif
(getbufferproc)shm_get_buffer,
(releasebufferproc)NULL,
};
@@ -536,12 +535,7 @@ static PyTypeObject SharedMemoryType = {
0, // tp_getattro
0, // tp_setattro
&SharedMemory_as_buffer, // tp_as_buffer
- // Python 2 needs the extra tp_flags Py_TPFLAGS_HAVE_NEWBUFFER.
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
-#if PY_MAJOR_VERSION == 2
- | Py_TPFLAGS_HAVE_NEWBUFFER
-#endif
- , // tp_flags
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
"System V shared memory object", // tp_doc
0, // tp_traverse
0, // tp_clear
@@ -752,7 +746,6 @@ static PyMethodDef module_methods[ ] = {
};
-#if PY_MAJOR_VERSION > 2
static struct PyModuleDef this_module = {
PyModuleDef_HEAD_INIT, // m_base
"sysv_ipc", // m_name
@@ -764,20 +757,10 @@ static struct PyModuleDef this_module = {
NULL, // m_clear
NULL // m_free
};
-#endif
-
-
-/* Module init function */
-#if PY_MAJOR_VERSION > 2
-#define SYSV_IPC_INIT_FUNCTION_NAME PyInit_sysv_ipc
-#else
-#define SYSV_IPC_INIT_FUNCTION_NAME initsysv_ipc
-#endif
-
/* Module init function */
PyMODINIT_FUNC
-SYSV_IPC_INIT_FUNCTION_NAME(void) {
+PyInit_sysv_ipc(void) {
PyObject *module;
PyObject *module_dict;
@@ -785,11 +768,7 @@ SYSV_IPC_INIT_FUNCTION_NAME(void) {
// random keys.
srand((unsigned int)time(NULL));
-#if PY_MAJOR_VERSION > 2
module = PyModule_Create(&this_module);
-#else
- module = Py_InitModule3("sysv_ipc", module_methods, "System V IPC module");
-#endif
if (!module)
goto error_return;
@@ -883,15 +862,9 @@ SYSV_IPC_INIT_FUNCTION_NAME(void) {
else
PyDict_SetItemString(module_dict, "NotAttachedError", pNotAttachedException);
-#if PY_MAJOR_VERSION > 2
return module;
-#endif
error_return:
-#if PY_MAJOR_VERSION > 2
return NULL;
-#else
- ; // Nothing to do
-#endif
}
diff --git a/tests/base.py b/tests/base.py
index 0fe122d..77644c4 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -1,16 +1,11 @@
# Python imports
-# Don't add any from __future__ imports here. This code should execute
-# against standard Python.
import unittest
import random
-import sys
import time
# Project imports
import sysv_ipc
-IS_PY3 = (sys.version_info[0] == 3)
-
def make_key():
"""Generate a random key suitable for an IPC object."""
diff --git a/tests/test_memory.py b/tests/test_memory.py
index f35272d..66d78bd 100644
--- a/tests/test_memory.py
+++ b/tests/test_memory.py
@@ -1,15 +1,10 @@
# Python imports
-# Don't add any from __future__ imports here. This code should execute
-# against standard Python.
import unittest
import time
import os
# Project imports
-# Hack -- add tests directory to sys.path so Python 3 can find base.py.
-import sys
-sys.path.insert(0, os.path.join(os.getcwd(), 'tests')) # noqa - tell flake8 to chill
-import base as tests_base
+from .base import Base, make_key, sleep_past_granularity
import sysv_ipc
# Not tested --
@@ -18,7 +13,7 @@ import sysv_ipc
# - attempt to write to segment attached with SHM_RDONLY gives a segfault under OS X and Linux.
-class SharedMemoryTestBase(tests_base.Base):
+class SharedMemoryTestBase(Base):
"""base class for SharedMemory test classes"""
# SIZE should be something that's not a power of 2 since that's more
# likely to expose odd behavior.
@@ -35,8 +30,7 @@ class SharedMemoryTestBase(tests_base.Base):
def assertWriteToReadOnlyPropertyFails(self, property_name, value):
"""test that writing to a readonly property raises TypeError"""
- tests_base.Base.assertWriteToReadOnlyPropertyFails(self, self.mem,
- property_name, value)
+ Base.assertWriteToReadOnlyPropertyFails(self, self.mem, property_name, value)
class TestSharedMemoryCreation(SharedMemoryTestBase):
@@ -61,7 +55,7 @@ class TestSharedMemoryCreation(SharedMemoryTestBase):
def test_IPC_CREAT_new(self):
"""tests sysv_ipc.IPC_CREAT to create a new SharedMemory without IPC_EXCL"""
# I can't pass None for the name unless I also pass IPC_EXCL.
- key = tests_base.make_key()
+ key = make_key()
# Note: this method of finding an unused key is vulnerable to a race
# condition. It's good enough for test, but don't copy it for use in
@@ -75,7 +69,7 @@ class TestSharedMemoryCreation(SharedMemoryTestBase):
except sysv_ipc.ExistentialError:
key_is_available = True
else:
- key = tests_base.make_key()
+ key = make_key()
mem = sysv_ipc.SharedMemory(key, sysv_ipc.IPC_CREAT, size=sysv_ipc.PAGE_SIZE)
@@ -337,7 +331,7 @@ class TestSharedMemoryPropertiesAndAttributes(SharedMemoryTestBase):
"""exercise SharedMemory.last_attach_time"""
self.mem.detach()
original_last_attach_time = self.mem.last_attach_time
- tests_base.sleep_past_granularity()
+ sleep_past_granularity()
# I can't record exactly when this attach() happens, but as long as it is within 5 seconds
# of the assertion happening, this test will pass.
self.mem.attach()
@@ -349,7 +343,7 @@ class TestSharedMemoryPropertiesAndAttributes(SharedMemoryTestBase):
def test_property_last_detach_time(self):
"""exercise SharedMemory.last_detach_time"""
original_last_detach_time = self.mem.last_detach_time
- tests_base.sleep_past_granularity()
+ sleep_past_granularity()
# I can't record exactly when this detach() happens, but as long as it is within 5 seconds
# of the assertion happening, this test will pass.
self.mem.detach()
@@ -361,7 +355,7 @@ class TestSharedMemoryPropertiesAndAttributes(SharedMemoryTestBase):
def test_property_last_change_time(self):
"""exercise SharedMemory.last_change_time"""
original_last_change_time = self.mem.last_change_time
- tests_base.sleep_past_granularity()
+ sleep_past_granularity()
# I can't record exactly when this last_change_time is set, but as long as it is within
# 5 seconds of the assertion happening, this test will pass.
# The statement below might seem like a no-op, but setting the UID to any value triggers
@@ -416,8 +410,7 @@ class BufferProtocolTest(unittest.TestCase):
ASCII_A = 0x61
self.alphabet = ''.join([chr(ASCII_A + i) for i in range(26)])
- if tests_base.IS_PY3:
- self.alphabet = bytes(self.alphabet, 'ASCII')
+ self.alphabet = bytes(self.alphabet, 'ASCII')
self.mem.write(self.alphabet)
@@ -460,21 +453,16 @@ class BufferProtocolTest(unittest.TestCase):
self.assertEqual(len(mv), self.mem.size)
# Test slicing
- to_chr = lambda c: chr(c) if tests_base.IS_PY3 else c # noqa E731 (silence flake8)
- to_ord = lambda c: ord(c) if tests_base.IS_PY3 else c # noqa E731 (silence flake8)
- self.assertEqual([to_chr(c) for c in mv[3:6]],
- ['d', 'e', 'f'])
+ self.assertEqual([chr(c) for c in mv[3:6]], ['d', 'e', 'f'])
# Test writing to the memoryview
- mv[4] = to_ord('x')
+ mv[4] = ord('x')
- self.assertEqual([to_chr(c) for c in mv[3:6]],
- ['d', 'x', 'f'])
+ self.assertEqual([chr(c) for c in mv[3:6]], ['d', 'x', 'f'])
# Ensure changes to the underlying segment are reflected in the memoryview
self.mem.write(b'xxx')
- self.assertEqual([to_chr(c) for c in mv[:6]],
- ['x', 'x', 'x', 'd', 'x', 'f'])
+ self.assertEqual([chr(c) for c in mv[:6]], ['x', 'x', 'x', 'd', 'x', 'f'])
if __name__ == '__main__':
diff --git a/tests/test_message_queues.py b/tests/test_message_queues.py
index 650465c..d65fb20 100644
--- a/tests/test_message_queues.py
+++ b/tests/test_message_queues.py
@@ -1,23 +1,19 @@
# Python imports
-# Don't add any from __future__ imports here. This code should execute
-# against standard Python.
import unittest
import time
import os
import numbers
+import sys
# Project imports
import sysv_ipc
-# Hack -- add tests directory to sys.path so Python 3 can find base.py.
-import sys
-sys.path.insert(0, os.path.join(os.getcwd(), 'tests')) # noqa - tell flake8 to chill
-import base as tests_base
+from .base import Base, make_key, sleep_past_granularity
# Not tested --
# - mode seems to be settable and readable, but ignored by the OS
-class MessageQueueTestBase(tests_base.Base):
+class MessageQueueTestBase(Base):
"""base class for MessageQueue test classes"""
def setUp(self):
self.mq = sysv_ipc.MessageQueue(None, sysv_ipc.IPC_CREX)
@@ -28,8 +24,7 @@ class MessageQueueTestBase(tests_base.Base):
def assertWriteToReadOnlyPropertyFails(self, property_name, value):
"""test that writing to a readonly property raises TypeError"""
- tests_base.Base.assertWriteToReadOnlyPropertyFails(self, self.mq,
- property_name, value)
+ Base.assertWriteToReadOnlyPropertyFails(self, self.mq, property_name, value)
class TestMessageQueueCreation(MessageQueueTestBase):
@@ -50,7 +45,7 @@ class TestMessageQueueCreation(MessageQueueTestBase):
def test_IPC_CREAT_new(self):
"""tests sysv_ipc.IPC_CREAT to create a new MessageQueue without IPC_EXCL"""
# I can't pass None for the name unless I also pass IPC_EXCL.
- key = tests_base.make_key()
+ key = make_key()
# Note: this method of finding an unused key is vulnerable to a race
# condition. It's good enough for test, but don't copy it for use in
@@ -64,7 +59,7 @@ class TestMessageQueueCreation(MessageQueueTestBase):
except sysv_ipc.ExistentialError:
key_is_available = True
else:
- key = tests_base.make_key()
+ key = make_key()
mq = sysv_ipc.MessageQueue(key, sysv_ipc.IPC_CREAT)
@@ -289,7 +284,7 @@ class TestMessageQueuePropertiesAndAttributes(MessageQueueTestBase):
# Note that last_change_time doesn't start out as 0 (unlike e.g. last_receive_time), so
# I don't test that here.
original_last_change_time = self.mq.last_change_time
- tests_base.sleep_past_granularity()
+ sleep_past_granularity()
# This might seem like a no-op, but setting the UID to any value triggers a call that
# should set last_change_time.
self.mq.uid = self.mq.uid
diff --git a/tests/test_module.py b/tests/test_module.py
index 4889e08..fadf6cc 100644
--- a/tests/test_module.py
+++ b/tests/test_module.py
@@ -1,23 +1,19 @@
# Python imports
-# Don't add any from __future__ imports here. This code should execute
-# against standard Python.
import unittest
import os
import resource
import warnings
import numbers
+import tempfile
# Project imports
import sysv_ipc
-# Hack -- add tests directory to sys.path so Python 3 can find base.py.
-import sys
-sys.path.insert(0, os.path.join(os.getcwd(), 'tests')) # noqa - tell flake8 to chill
-import base as tests_base
+from .base import Base
ONE_MILLION = 1000000
-class TestModuleConstants(tests_base.Base):
+class TestModuleConstants(Base):
"""Check that the sysv_ipc module-level constants are defined as expected"""
def test_constant_values(self):
"""test that constants are what I expect"""
@@ -45,7 +41,7 @@ class TestModuleConstants(tests_base.Base):
self.assertIsInstance(sysv_ipc.__copyright__, str)
-class TestModuleErrors(tests_base.Base):
+class TestModuleErrors(Base):
"""Exercise the exceptions defined by the module"""
def test_errors(self):
self.assertTrue(issubclass(sysv_ipc.Error, Exception))
@@ -56,7 +52,7 @@ class TestModuleErrors(tests_base.Base):
self.assertTrue(issubclass(sysv_ipc.NotAttachedError, sysv_ipc.Error))
-class TestModuleFunctions(tests_base.Base):
+class TestModuleFunctions(Base):
"""Exercise the sysv_ipc module-level functions"""
def test_attach(self):
"""Exercise attach()"""
@@ -127,6 +123,14 @@ class TestModuleFunctions(tests_base.Base):
"""Ensure ftok() returns an int"""
self.assertIsInstance(sysv_ipc.ftok('.', 42, silence_warning=True), numbers.Integral)
+ def test_ftok_raises_os_error(self):
+ """Ensure ftok() failure raises an exception"""
+ with tempfile.TemporaryDirectory() as tmp_dir_name:
+ # Create a path that should cause ftok() to fail.
+ does_not_exist_path = os.path.join(tmp_dir_name, "does_not_exist")
+ with self.assertRaises(OSError):
+ sysv_ipc.ftok(does_not_exist_path, 42, silence_warning=True)
+
def test_remove_semaphore(self):
"""Exercise remove_semaphore()"""
sem = sysv_ipc.Semaphore(None, sysv_ipc.IPC_CREX)
diff --git a/tests/test_semaphores.py b/tests/test_semaphores.py
index 2540992..4dd87e2 100644
--- a/tests/test_semaphores.py
+++ b/tests/test_semaphores.py
@@ -1,6 +1,4 @@
# Python imports
-# Don't add any from __future__ imports here. This code should execute
-# against standard Python.
import unittest
import datetime
import time
@@ -8,10 +6,7 @@ import os
# Project imports
import sysv_ipc
-# Hack -- add tests directory to sys.path so Python 3 can find base.py.
-import sys
-sys.path.insert(0, os.path.join(os.getcwd(), 'tests')) # noqa - tell flake8 to chill
-import base as tests_base
+from .base import Base, make_key
# Not tested --
# - mode seems to be settable and readable, but ignored by the OS
@@ -28,7 +23,7 @@ import base as tests_base
N_RELEASES = 1000000 # 1 million
-class SemaphoreTestBase(tests_base.Base):
+class SemaphoreTestBase(Base):
"""base class for Semaphore test classes"""
def setUp(self):
self.sem = sysv_ipc.Semaphore(None, sysv_ipc.IPC_CREX, initial_value=1)
@@ -39,7 +34,7 @@ class SemaphoreTestBase(tests_base.Base):
def assertWriteToReadOnlyPropertyFails(self, property_name, value):
"""test that writing to a readonly property raises TypeError"""
- tests_base.Base.assertWriteToReadOnlyPropertyFails(self, self.sem, property_name, value)
+ Base.assertWriteToReadOnlyPropertyFails(self, self.sem, property_name, value)
def assertDeltasCloseEnough(self, delta_a, delta_b):
"""Compare two datetime.timedeltas and ensure they're within < 1 second of one another.
@@ -75,7 +70,7 @@ class TestSemaphoreCreation(SemaphoreTestBase):
def test_IPC_CREAT_new(self):
"""tests sysv_ipc.IPC_CREAT to create a new semaphore without IPC_EXCL"""
# I can't pass None for the name unless I also pass IPC_EXCL.
- key = tests_base.make_key()
+ key = make_key()
# Note: this method of finding an unused key is vulnerable to a race
# condition. It's good enough for test, but don't copy it for use in
@@ -88,7 +83,7 @@ class TestSemaphoreCreation(SemaphoreTestBase):
except sysv_ipc.ExistentialError:
key_is_available = True
else:
- key = tests_base.make_key()
+ key = make_key()
sem = sysv_ipc.Semaphore(key, sysv_ipc.IPC_CREAT)
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/debug/.build-id/4e/945a5df23b09b9b66a79a6e8fd85022c1dfa16.debug -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.1.0.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.1.0.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.1.0.egg-info/top_level.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc.cpython-310-x86_64-linux-gnu.so
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/debug/.build-id/2a/d3191ed97151f671c92b2045d681c9ac21f21e.debug -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.0.0.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.0.0.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc-1.0.0.egg-info/top_level.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/sysv_ipc.cpython-311-x86_64-linux-gnu.so
Control files of package python3-sysv-ipc: lines which differ (wdiff format)
Depends: python3 (<< 3.12), 3.11), python3 (>= 3.11~), 3.10~), libc6 (>= 2.14)
Control files of package python3-sysv-ipc-dbgsym: lines which differ (wdiff format)
Build-Ids: 2ad3191ed97151f671c92b2045d681c9ac21f21e 4e945a5df23b09b9b66a79a6e8fd85022c1dfa16