Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add python type information for MessageQueue class #54

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ demo/*.o
demo/premise
demo/conclusion
post_dist.py
**/*.egg-info
tests/stubs/
posix_ipc*.so
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ matrix:
osx_image: xcode11.2 # Python 3.7
language: shell # 'language: python' is an error on Travis CI macOS

install: python setup.py install
install: python setup.py install && python pip install pybind11-stubgen
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I haven't used travis CI before, so I dont know if this is the correct place to do this.

script: python -m unittest discover
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include INSTALL LICENSE VERSION
include README.md USAGE.md history.md
include setup.py prober.py
include posix_ipc_module.c
include posix_ipc.pyi
recursive-include prober *.c
recursive-include demo *.h *.c *.py *.sh *.png *.txt *.md
recursive-include demo2 *.py *.txt *.png *.md
Expand Down
118 changes: 118 additions & 0 deletions posix_ipc/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from collections.abc import Callable
from typing import Any

__all__ = [
"BusyError",
"Error",
"ExistentialError",
"MESSAGE_QUEUES_SUPPORTED",
"MessageQueue",
"O_CREAT",
"O_CREX",
"O_EXCL",
"O_NONBLOCK",
"O_RDONLY",
"O_RDWR",
"O_TRUNC",
"O_WRONLY",
"PAGE_SIZE",
"PermissionsError",
"QUEUE_MESSAGES_MAX_DEFAULT",
"QUEUE_MESSAGE_SIZE_MAX_DEFAULT",
"QUEUE_PRIORITY_MAX",
"SEMAPHORE_TIMEOUT_SUPPORTED",
"SEMAPHORE_VALUE_MAX",
"SEMAPHORE_VALUE_SUPPORTED",
"Semaphore",
"SharedMemory",
"SignalError",
"USER_SIGNAL_MAX",
"USER_SIGNAL_MIN",
"unlink_message_queue",
"unlink_semaphore",
"unlink_shared_memory",
]

# module functions

def unlink_semaphore(name: str) -> None: ...
def unlink_shared_memory(name: str) -> None: ...
def unlink_message_queue(name: str) -> None: ...

# module constants

O_CREX: int
O_CREAT: int
O_EXCL: int
O_TRUNC: int
PAGE_SIZE: int
SEMAPHORE_TIMEOUT_SUPPORTED: bool
SEMAPHORE_VALUE_SUPPORTED: bool
SEMAPHORE_VALUE_MAX: int
MESSAGE_QUEUES_SUPPORTED: bool
QUEUE_MESSAGES_MAX_DEFAULT: int
QUEUE_MESSAGE_SIZE_MAX_DEFAULT: int
QUEUE_PRIORITY_MAX: int
USER_SIGNAL_MIN: int
USER_SIGNAL_MAX: int
VERSION: str
O_NONBLOCK: int
O_RDONLY: int
O_RDWR: int
O_WRONLY: int

# errors

class SignalError(Error):
pass

class PermissionsError(Error):
pass

class BusyError(Error):
pass

class Error(Exception):
pass

class ExistentialError(Error):
pass

# classes

class Semaphore:
def __init__(self, name: str, flags: int = ..., mode: int = ..., initial_value: int = ...) -> None: ...
def acquire(self, timeout: float | None = ...) -> None: ...
def release(self) -> None: ...
def close(self) -> None: ...
def unlink(self) -> None: ...
def __enter__(self) -> None: ...
def __exit__(self) -> None: ...

class SharedMemory:
"""POSIX semaphore object."""

def __init__(
self, name: str, flags: int = ..., mode: int = ..., size: int = ..., read_only: bool = ...
) -> None: ...
def close_fd(self) -> None: ...
def fileno(self) -> None: ...
def unlink(self) -> None: ...

class MessageQueue:
def __init__(
self,
name: str | None,
flags: int = ...,
mode: int = ...,
max_messages: int = ...,
max_message_size: int = ...,
read: bool = ...,
write: bool = ...,
) -> None: ...
def send(self, message: str | bytes, timeout: float | None = ..., priority: int = ...) -> None: ...
def receive(self, timeout: float | None = ...) -> tuple[bytes, int]: ...
def request_notification(self, notification: int | tuple[Callable[[Any], None], Any] | None = ...) -> None: ...
def close(self) -> None: ...
def fileno(self) -> None: ...
def unlink(self) -> None: ...
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,8 @@
classifiers=classifiers,
license=license,
keywords=keywords,
ext_modules=ext_modules
ext_modules=ext_modules,
packages=[name],
package_data={"": ["*.pyi"]},
include_package_data=True,
)
38 changes: 38 additions & 0 deletions tests/test_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Test that the stubs generated by pybind11-stubgen are compatible with the hand-crafted ones."""

import inspect
import os
import sys
import unittest
from unittest.mock import patch

import posix_ipc as handcrafted
from pybind11_stubgen import main

from . import base as tests_base


class TestPybind11TypesCompatibility(tests_base.Base):
"""Test that the stubs generated by pybind11-stubgen are compatible with the hand-crafted ones."""

def setUp(self):
"""Generate the type stubs."""
# mock the sys.argv - I dont want to do a subprocess.run because it can be error prone depending on which
# packages you may have installed.
with patch.object(sys, 'argv', ["pybind11-stubgen", "posix_ipc", "-o", "tests/stubs"]):
main()
os.rename("tests/stubs/posix_ipc.pyi", "tests/stubs/__init__.py") # to make the stubs importable

def test_messagequeue(self):
"""Test the generated MessageQueue is the same as the hand-crafted one."""
from . import stubs as generated
generated_methods = inspect.getmembers(generated.MessageQueue, predicate=inspect.ismethod)
crafted_methods = inspect.getmembers(handcrafted.MessageQueue, predicate=inspect.ismethod)
crafted_method_names = [m[0] for m in crafted_methods]
for method in generated_methods:
self.assertTrue(method[0] in crafted_method_names)
# NOTE: We can't compare the func signatures, because pybind11-stubgen doesnt generate types for parameters.


if __name__ == '__main__':
unittest.main()