Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Packaging stub files

Tags:

Let's say I have very simple package with a following structure:

.
├── foo
│   ├── bar
│   │   └── __init__.py
│   └── __init__.py
└── setup.py

Content of the files:

  • setup.py:

    from distutils.core import setup
    
    setup(
        name='foobar',
        version='',
        packages=['foo', 'foo.bar'],
        url='',
        license='Apache License 2.0',
        author='foobar',
        author_email='',
        description=''
    )
    
  • foo/bar/__init__.py:

    def foobar(x):
        return x
    
  • The remaining files are empty.

I install the package using pip:

cd foobar
pip install .

and can confirm it is installed correctly.

Now I want to create a separate package with stub files:

.
├── foo
│   ├── bar
│   │   └── __init__.pyi
│   └── __init__.pyi
└── setup.py

Content of the files:

  • setup.py:

    from distutils.core import setup
    import sys
    import pathlib
    
    setup(
        name='foobar_annot',
        version='',
        packages=['foo', 'foo.bar'],
        url='',
        license='Apache License 2.0',
        author='foobar',
        author_email='',
        description='',
        data_files=[
            (
                'shared/typehints/python{}.{}/foo/bar'.format(*sys.version_info[:2]),
                ["foo/bar/__init__.pyi"]
            ),
        ],
    )
    
  • foo.bar.__init__.pyi:

    def foobar(x: int) -> int: ...
    

I can install this package, see that it creates anaconda3/shared/typehints/python3.5/foo/bar/__init__.pyi in my Anaconda root, but it doesn't look like it is recognized by PyCharm (I get no warnings). When I place pyi file in the main package everything works OK.

I would be grateful for any hints how to make this work:

  • I've been trying to make some sense from PEP 484 - Storing and distributing stub files but to no avail. Even pathlib part seem to offend my version of distutils
  • PY-18597 and https://github.com/python/mypy/issues/1190#issuecomment-188526651 seem to be related but somehow I cannot connect the dots.
  • I tried putting stubs in the .PyCharmX.X/config/python-skeletons but it didn't help.'

Some things that work, but don't resolve the problem:

  • Putting stub files in the current project and marking as sources.
  • Adding stub package root to the interpreter path (at least in some simple cases).

So the questions: How to create a minimal, distributable package with Python stubs, which will be recognized by existing tools. Based on the experiments I suspect one of two problems:

  • I misunderstood the structure which should be created by the package in the shared/typehints/pythonX.Y - if this is true, how should I define data_files?
  • PyCharm doesn't consider these files at all (this seem to be contradicted by some comments in the linked issue).
  • It suppose to work just fine, but I made some configure mistake and looking for external problem which doesn't exist.
  • Are there any established procedures to troubleshoot problems like this?
like image 482
user7484208 Avatar asked Jan 28 '17 22:01

user7484208


People also ask

What is type stub file?

A stub file is a computer file that appears to the user to be on disk and immediately available for use, but is actually held either in part or entirely on a different storage medium.

How do I create a stub file?

To generate a stub file use javah 's -stubs option. Again remember to run javah on the Java class. By default, javah will place the resulting stub file in the same directory as the . class file.

What are Python stub files?

What is a stub file? It is a file with the . pyi extension, which describes the Python type information, both input and return for functions and omits the logical part.


1 Answers

Problem is that you didn't include the foo/__init__.pyi file in your stub distribution. Even though it's empty, it makes foo a stub files package, and enables search for foo.bar.

You can modify the data_files in your setup.py to include both

data_files=[
    (
        'shared/typehints/python{}.{}/foo/bar'.format(*sys.version_info[:2]),
        ["foo/bar/__init__.pyi"]
    ),

    (
        'shared/typehints/python{}.{}/foo'.format(*sys.version_info[:2]),
        ["foo/__init__.pyi"]
    ),
],
like image 191
matusko Avatar answered Nov 12 '22 20:11

matusko