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

Export type annotations for public use #95

Merged
merged 17 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
sudo apt-get install -y pkg-config gcc ninja-build meson

- name: Install Python dependencies (misc)
run: pip install setuptools trio pytest pytest_trio sphinx
run: pip install setuptools trio pytest pytest_trio mypy sphinx

- name: Install Python dependencies (Cython 0.29)
if: ${{ matrix.cython-version == '0.29' }}
Expand All @@ -40,15 +40,19 @@ jobs:
if: ${{ matrix.cython-version == '3.0' }}
run: pip install "Cython>=3"

- name: Test
- name: Build
bgilbert marked this conversation as resolved.
Show resolved Hide resolved
run: |
set -e
# Disable developer mode, so that build does not suddenly break if
# e.g. a newer compiler version results in new warning messages.
rm MANIFEST.in
python setup.py build_cython
python setup.py build_ext --inplace

pytest -v -rs test/
- name: Test
run: pytest -v -rs test/

- name: Typecheck
run: mypy

sphinx-build -b html rst doc/html
- name: Build docs
run: sphinx-build -b html rst doc/html
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ build/
dist/
doc/html/
doc/doctrees/
src/pyfuse3.c
src/pyfuse3*.so
src/pyfuse3/__init__.c
src/pyfuse3/__init__*.so
test/.cache/
__pycache__
test/.pytest_cache/
Expand Down
26 changes: 21 additions & 5 deletions Changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@

.. currentmodule:: pyfuse3

Unreleased Changes
==================

* Move ``_pyfuse3`` to ``pyfuse3._pyfuse3`` and add a compatibility wrapper
for the old name.

* Move ``pyfuse3_asyncio`` to ``pyfuse3.asyncio`` and add a compatibility
wrapper for the old name.

* Add `bytes` subclass `XAttrNameT` as the type of extended attribute names.

* Various fixes to type annotations.

* Add ``py.typed`` marker to enable external use of type annotations.


Release 3.3.0 (2023-08-06)
==========================

Expand Down Expand Up @@ -68,7 +84,7 @@ Release 3.2.1 (2021-09-17)

* Add type annotations

* Passing a XATTR_CREATE or XATTR_REPLACE to setxattr() is now working
* Passing a XATTR_CREATE or XATTR_REPLACE to `setxattr` is now working
correctly.

Release 3.2.0 (2020-12-30)
Expand Down Expand Up @@ -97,8 +113,8 @@ Release 3.1.0 (2020-05-31)
Release 3.0.0 (2020-05-08)
==========================

* Changed `create` handler to return a `FileInfo` struct to allow for
modification of certain kernel file attributes, e.g. ``direct_io``.
* Changed `~Operations.create` handler to return a `FileInfo` struct to allow
for modification of certain kernel file attributes, e.g. ``direct_io``.

Note that this change breaks backwards compatibility, code that depends
on the old behavior needs to be changed.
Expand All @@ -107,8 +123,8 @@ Release 3.0.0 (2020-05-08)
Release 2.0.0
=============

* Changed `open` handler to return the new `FileInfo` struct to allow for
modification of certain kernel file attributes, e.g. ``direct_io``.
* Changed `~Operations.open` handler to return the new `FileInfo` struct to
allow for modification of certain kernel file attributes, e.g. ``direct_io``.

Note that this change breaks backwards compatibility, code that depends on the old
behavior needs to be changed.
Expand Down
2 changes: 1 addition & 1 deletion examples/hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# to load the module from there first.
basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3.pyx'))):
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3', '__init__.pyx'))):
sys.path.insert(0, os.path.join(basedir, 'src'))

from argparse import ArgumentParser
Expand Down
6 changes: 3 additions & 3 deletions examples/hello_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# to load the module from there first.
basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3.pyx'))):
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3', '__init__.pyx'))):
sys.path.insert(0, os.path.join(basedir, 'src'))

from argparse import ArgumentParser
Expand All @@ -38,7 +38,7 @@
import logging
import errno
import pyfuse3
import pyfuse3_asyncio
import pyfuse3.asyncio

try:
import faulthandler
Expand All @@ -48,7 +48,7 @@
faulthandler.enable()

log = logging.getLogger(__name__)
pyfuse3_asyncio.enable()
pyfuse3.asyncio.enable()

class TestFs(pyfuse3.Operations):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion examples/passthroughfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
# to load the module from there first.
basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3.pyx'))):
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3', '__init__.pyx'))):
sys.path.insert(0, os.path.join(basedir, 'src'))

import pyfuse3
Expand Down
2 changes: 1 addition & 1 deletion examples/tmpfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
# to load the module from there first.
basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3.pyx'))):
os.path.exists(os.path.join(basedir, 'src', 'pyfuse3', '__init__.pyx'))):
sys.path.insert(0, os.path.join(basedir, 'src'))

import pyfuse3
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.mypy]
mypy_path = ["$MYPY_CONFIG_FILE_DIR/src"]
packages = ["pyfuse3"]
modules = ["_pyfuse3", "pyfuse3_asyncio"]
namespace_packages = false
strict = true
9 changes: 5 additions & 4 deletions rst/asyncio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

By default, pyfuse3 uses asynchronous I/O using Trio_ (and most of the
documentation assumes that you are using Trio). If you'd rather use
asyncio, import the *pyfuse3_asyncio* module and call its
*enable()* function before using *pyfuse3*. For example::
asyncio, import the *pyfuse3.asyncio* module (*pyfuse3_asyncio* in 3.3.0 and
earlier) and call its *enable()* function before using *pyfuse3*.
For example::

import pyfuse3
import pyfuse3_asyncio
import pyfuse3.asyncio

pyfuse3_asyncio.enable()
pyfuse3.asyncio.enable()

# Use pyfuse3 as usual from here on.

Expand Down
8 changes: 8 additions & 0 deletions rst/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

def setup(app):
# Mangle NewTypes re-exported from pyfuse3._pyfuse3 so they appear to
# come from their canonical location at the top of the package
import pyfuse3
for name in ('FileHandleT', 'FileNameT', 'FlagT', 'InodeT', 'ModeT',
'XAttrNameT'):
getattr(pyfuse3, name).__module__ = 'pyfuse3'


# -- Options for HTML output ---------------------------------------------------

Expand Down
35 changes: 35 additions & 0 deletions rst/data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,37 @@

.. autoexception:: FUSEError

.. autoclass currently doesn't work for NewTypes
.. https://github.com/sphinx-doc/sphinx/issues/11552

.. class:: FileHandleT

A subclass of `int`, representing an integer file handle produced by a
`~Operations.create`, `~Operations.open`, or `~Operations.opendir` call.

.. class:: FileNameT

A subclass of `bytes`, representing a file name, with no embedded
zero-bytes (``\0``).

.. class:: FlagT

A subclass of `int`, representing flags modifying the behavior of an
operation.

.. class:: InodeT

A subclass of `int`, representing an inode number.

.. class:: ModeT

A subclass of `int`, representing a file mode.

.. class:: XAttrNameT

A subclass of `bytes`, representing an extended attribute name, with no
embedded zero-bytes (``\0``).

.. autoclass:: RequestContext

.. attribute:: pid
Expand Down Expand Up @@ -163,3 +194,7 @@
If this attribute is true, it signals the `Operations.setattr`
method that the `~EntryAttributes.st_size` field contains an
updated value.

.. autoclass:: ReaddirToken

An identifier for a particular `~Operations.readdir` invocation.
2 changes: 1 addition & 1 deletion rst/fuse_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@

.. py:data:: trio_token

Set to the value returned by `trio.lowlevel.current_trio_token()` while `main()` is
Set to the value returned by `trio.lowlevel.current_trio_token` while `main` is
running. Can be used by other threads to run code in the main loop through
`trio.from_thread.run`.
8 changes: 5 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ def main():

link_args = pkg_config('fuse3', cflags=False, ldflags=True, min_ver='3.2.0')
link_args.append('-lpthread')
c_sources = ['src/pyfuse3.c']
c_sources = ['src/pyfuse3/__init__.c']

if os.uname()[0] in ('Linux', 'GNU/kFreeBSD'):
link_args.append('-lrt')
elif os.uname()[0] == 'Darwin':
c_sources.append('src/darwin_compat.c')
c_sources.append('src/pyfuse3/darwin_compat.c')

setuptools.setup(
name='pyfuse3',
Expand Down Expand Up @@ -128,9 +128,11 @@ def main():
tests_require=['pytest >= 3.4.0', 'pytest-trio'],
python_requires='>=3.8',
package_dir={'': 'src'},
packages=['pyfuse3'],
py_modules=['_pyfuse3', 'pyfuse3_asyncio'],
package_data={'pyfuse3': ['py.typed']},
provides=['pyfuse3'],
ext_modules=[Extension('pyfuse3', c_sources,
ext_modules=[Extension('pyfuse3.__init__', c_sources,
extra_compile_args=compile_args,
extra_link_args=link_args)],
cmdclass={'build_cython': build_cython},
Expand Down
Loading