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

[Feature Request] Official FreeBSD support #261

Open
yurivict opened this issue Jul 22, 2023 · 9 comments
Open

[Feature Request] Official FreeBSD support #261

yurivict opened this issue Jul 22, 2023 · 9 comments

Comments

@yurivict
Copy link

=================================== FAILURES ===================================
_____________________________ test_coerce_hint_any _____________________________

    def test_coerce_hint_any() -> None:
        '''
        Test the private
        :func:`beartype._check.convert.convcoerce.coerce_hint_any` coercer.
        '''
    
        # ..................{ IMPORTS                            }..................
        # Defer test-specific imports.
        from beartype._check.convert.convcoerce import coerce_hint_any
        from beartype._util.py.utilpyversion import (
            IS_PYTHON_AT_LEAST_3_10,
            IS_PYTHON_AT_LEAST_3_9,
        )
    
        # ..................{ CORE                               }..................
        # Assert this coercer preserves an isinstanceable type as is.
        assert coerce_hint_any(int) is int
    
        # ..................{ PEP 585                            }..................
        # If the active Python interpreter targets Python >= 3.9 and thus supports
        # PEP 585...
        if IS_PYTHON_AT_LEAST_3_9:
            # Arbitrary PEP 585-compliant type hint.
            hint_pep585 = list[int]
   
            # Assert this coercer preserves the first passed instance of a PEP
            # 585-compliant type hint as is.
>           assert coerce_hint_any(hint_pep585) is hint_pep585
E           assert list[int] is list[int]
E            +  where list[int] = <function coerce_hint_any at 0x9712688b0>(list[int])

beartype_test/a00_unit/a60_check/a20_conv/test_convcoerce.py:92: AssertionError
=========================== short test summary info ============================
SKIPPED [1] beartype_test/a90_func/z90_lib/a90_nuitka/test_nuitka.py:31: Command "gcc" not found.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a90_pep/test_decorpep647.py:21: Python 3.9.17 < 3.10.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a00_mod/test_decor_contextlib.py:21: Python 3.9.17 < 3.11.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a90_pep/test_decorpep673.py:21: Python 3.9.17 < 3.11.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a80_nonpep/mod/test_codepandera.py:22: could not import 'pandera.__init__': No module named 'pandera'
SKIPPED [1] beartype_test/a90_func/pep/test_pep561_static.py:169: Command "pyright" not found.
================== 1 failed, 288 passed, 6 skipped in 31.12s ===================
*** Error code 1


Version: 0.15.0
Python-3.9
FreeBSD 13.2

@leycec leycec changed the title 1 test fails [FreeBSD] test_coerce_hint_any() unit test fails Jul 25, 2023
@leycec
Copy link
Member

leycec commented Jul 25, 2023

Bizarreness. Clearly, FreeBSD is stranger even than I dared to contemplate. Thankfully, our test suite routinely passes under all officially supported platforms – including Linux, macOS, and Windows. Unthankfully, I have no reasonable means of testing migraine-inducing *BSD issues at the moment. I don't have a *BSD machine or VM at the moment; I barely have sufficient volunteer time to maintain @beartype on the three platforms we do officially support.

Allow me to wave my hands wildly about. Our continuous integration (CI) pipelines leverage GitHub Actions. That's good. GitHub Actions currently fails to offer a FreeBSD runner. That's bad. Without official support from Microsoft here, it's unclear either how or when exactly @beartype will be able to support Linux-adjacent platforms like FreeBSD and NetBSD. I feel the sadness and possible anger you also feel. 😞 :rage1: 😥

Let's quietly leave this open until Microsoft releases a *BSD runner to the huddled masses. Until then, please accept my heartfelt apology and a hollow promise to do better by the Butlerian Jihad of 201 BG. ...heh.

@leycec leycec changed the title [FreeBSD] test_coerce_hint_any() unit test fails [Feature Request] Official FreeBSD support Jul 25, 2023
@yurivict
Copy link
Author

yurivict commented Jul 25, 2023

[...] GitHub Actions currently fails to offer a FreeBSD runner [...]

This isn't true.

Here is an example of CI run set on GitHub that includes FreeBSD CI runs.

Here are instructions how to set it up.

@leycec
Copy link
Member

leycec commented Jul 25, 2023

Well, yes. Technically, you can run FreeBSD via third-party actions in simplistic pipelines devoted entirely to FreeBSD. Pragmatically, our pipeline is anything but simplistic; those actions don't appear to offer a usable Docker image that integrates with the standard strategy/matrix: approach provided by GitHub Actions.

@beartype needs something standard like this:

# In our ".github/workflow/python_test.yml" file:
...

# ....................{ MAIN                               }....................
jobs:
  # ...................{ TESTS                              }...................
  # Job iteratively exercising our test suite against all Python interpreters
  # supported by this package (and also measuring the coverage of that suite).
  tests:
    # ..................{ MATRIX                             }..................
    strategy:
      matrix:
        # List of all platform-specific Docker images to test against,
        # including:
        # * The latest Long-Term Service (LTS) release of Ubuntu Linux, still
        #   the most popular Linux distro and thus a sane baseline.
        # * The latest *whatever* release of Microsoft Windows. Although Linux
        #   and macOS are both POSIX-compliant and thus crudely comparable from
        #   the low-level CLI perspective, Windows is POSIX-noncompliant and
        #   thus heavily divergent from both macOS and Linux.
        # * The latest *whatever* release of Apple macOS. We don't particularly
        #   need to exercise tests on macOS, given the platform's patent
        #   POSIX-compliant low-level similarities to Linux, but... what the
        #   heck. Why not? Since this is the lowest priority, we defer macOS
        #   testing until last.
        platform: [ubuntu-latest, windows-latest, macos-latest]
        # ^------ *THIS IS WHERE @beartype NEEDS A "freebsd-latest" DOCKER IMAGE*

For @beartype to support FreeBSD, we really need GitHub itself to natively support FreeBSD with a freebsd-latest Docker image. Lacking that, it's unclear how exactly we could integrate FreeBSD support into our existing pipeline. We're definitely not leaving the confines of the standard strategy/matrix: approach. If we did that, we'd basically have to manually generate our entire jobs matrix by hand. It's hard enough maintaining this madness with GitHub's combinatorial generation of our jobs matrix against all supported Python versions + all supported platforms. I sigh. 😮‍💨

@yurivict
Copy link
Author

Version 0.16.0 has 2 failing tests:

========================================================================================= FAILURES ==========================================================================================
___________________________________________________________________________________ test_get_func_locals ____________________________________________________________________________________

    def test_get_func_locals() -> None:
        '''
        Test the
        :func:`beartype._util.func.utilfuncscope.get_func_locals` getter.
        '''
    
        # ..................{ IMPORTS                            }..................
        # Defer test-specific imports.
        from beartype.roar._roarexc import _BeartypeUtilCallableException
        from beartype.typing import Union
        from beartype._util.func.utilfuncmake import make_func
        from beartype._util.func.utilfuncscope import get_func_locals
        from pytest import raises
    
        # ..................{ CALLABLES                          }..................
        def and_summon_the_shadows_there():
            '''
            Arbitrary nested callable.
            '''
    
            return 'And tie a ribbon on those sheltering arms'
    
        # Arbitrary nested callable dynamically declared in-memory.
        when_the_ash_and_oak_and_the_birch_and_yew = make_func(
            func_name='when_the_ash_and_oak_and_the_birch_and_yew',
            func_code='''def when_the_ash_and_oak_and_the_birch_and_yew(): pass''',
        )
    
        # Arbitrary nested callables whose unqualified and fully-qualified names
        # are maliciously desynchronized below, exercising edge cases.
        def are_dressed_in_ribbons_fair(): pass
        def who_will_go_down_to_the_shady_groves(): pass
        are_dressed_in_ribbons_fair.__qualname__ = (
            'when_owls_call.the_breathless_moon')
        who_will_go_down_to_the_shady_groves.__qualname__ = (
            '<locals>.who_will_go_down_to_the_shady_groves')
    
        # ..................{ PASS ~ noop                        }..................
        # Assert this getter returns the empty dictionary for callables dynamically
        # declared in-memory.
>       assert get_func_locals(when_the_ash_and_oak_and_the_birch_and_yew) == {}
E       AssertionError: assert {'Chameleon':...d041160>, ...} == {}
E         Left contains 8 more items:
E         {'Chameleon': <class 'beartype_test.a00_unit.data.pep.pep563.data_pep563_club.Chameleon'>,
E          '__dict__': <attribute '__dict__' of 'Chameleon' objects>,
E          '__doc__': '\n'
E                     '    Arbitrary class declaring arbitrary methods.\n'
E                     '\n'
E                     '    Attributes\n'...
E         
E         ...Full output truncated (28 lines hidden), use '-vv' to show

beartype_test/a00_unit/a20_util/func/test_utilfuncscope.py:228: AssertionError
___________________________________________________________________________________ test_coerce_hint_any ____________________________________________________________________________________

    def test_coerce_hint_any() -> None:
        '''
        Test the private
        :func:`beartype._check.convert.convcoerce.coerce_hint_any` coercer.
        '''
    
        # ..................{ IMPORTS                            }..................
        # Defer test-specific imports.
        from beartype._check.convert.convcoerce import coerce_hint_any
        from beartype._util.py.utilpyversion import (
            IS_PYTHON_AT_LEAST_3_10,
            IS_PYTHON_AT_LEAST_3_9,
        )
    
        # ..................{ CORE                               }..................
        # Assert this coercer preserves an isinstanceable type as is.
        assert coerce_hint_any(int) is int
    
        # ..................{ PEP 585                            }..................
        # If the active Python interpreter targets Python >= 3.9 and thus supports
        # PEP 585...
        if IS_PYTHON_AT_LEAST_3_9:
            # Arbitrary PEP 585-compliant type hint.
            hint_pep585 = list[int]
    
            # Assert this coercer preserves the first passed instance of a PEP
            # 585-compliant type hint as is.
>           assert coerce_hint_any(hint_pep585) is hint_pep585
E           assert list[int] is list[int]
E            +  where list[int] = <function coerce_hint_any at 0x9171cb940>(list[int])

beartype_test/a00_unit/a60_check/a20_conv/test_convcoerce.py:92: AssertionError
================================================================================== short test summary info ==================================================================================
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a90_pep/test_decorpep435663.py:64: Python 3.9.17 < 3.11.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a00_mod/test_decor_contextlib.py:21: Python 3.9.17 < 3.11.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a90_pep/test_decorpep647.py:21: Python 3.9.17 < 3.10.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a90_pep/test_decorpep673.py:21: Python 3.9.17 < 3.11.0.
SKIPPED [1] beartype_test/a00_unit/a70_decor/a40_code/a80_nonpep/mod/test_codepandera.py:22: could not import 'pandera.__init__': No module named 'pandera'
SKIPPED [1] beartype_test/a00_unit/a70_decor/test_decorwrappee.py:303: Python 3.9.17 < 3.10.0.
SKIPPED [1] beartype_test/a90_func/z90_lib/a90_nuitka/test_nuitka.py:31: Command "gcc" not found.
SKIPPED [1] beartype_test/a90_func/pep/test_pep561_static.py:167: Command "pyright" not found.
========================================================================= 2 failed, 297 passed, 8 skipped in 36.34s =========================================================================
*** Error code 1

FreeBSD 13.2
Python-3.9

@leycec
Copy link
Member

leycec commented Sep 20, 2023

Yikes. That's genuinely awful. Python's official FreeBSD port doesn't appear to conform to the same API as Python's official Linux, macOS, and Windows ports. I have a dim inkling of what may be happening here – but only a dim inkling.

The underlying culprit? Probably the private sys._getframe() function. Technically, Python implementations are not required to implement that function. It's optional. It's also mandatory for performing call stack inspection and thus PEP 563 resolution (i.e., from __future__ import annotations), which is what the test_get_func_locals() unit test is exercising. I assumed sys._getframe() was implemented in a fairly standardized way across all CPython ports. Clearly, assumptions are bad.

The test_coerce_hint_any() unit test failure continues to make me scratch my head. That's an even weirder one. I don't even have a dim inkling why that might be failing in such an obscure fashion.

GitHub itself is unlikely to offer FreeBSD runners for GitHub Actions anytime soon. It kinda looks like I should locally spin up a FreeBSD virtual machine at some point in the near future. This is already bad and only getting worse.

FreeBSD: y u gotta be so different, huh? 😮‍💨

@yurivict
Copy link
Author

I have the instructions on how to install FreeBSD and compile the port and run tests:

1. Install the [FreeBSD VM image](https://download.freebsd.org/ftp/releases/VM-IMAGES/13.1-RELEASE/amd64/Latest/) into VirtualBox.
2. Boot FreeBSD
3. Install git: pkg install git
4. Check out the ports tree: git clone https://git.FreeBSD.org/ports.git /usr/ports
5. cd /usr/ports/devel/py-beartype
6. Install dependencies: pkg install -A `make missing`
7. Build: make
8. Run tests: make test

@leycec
Copy link
Member

leycec commented Sep 21, 2023

Awesome-sauce. Thanks so much for that exhaustive (and probably exhausting) write-up. Because I am lazy, I shouldn't promise that I will do this immediately or even soon. But I should do this sooner than later. Please prod me with a ping here if I fail to do this by the end of the year.

FreeBSD is a super-fun platform. It's shameful that @beartype currently fails FreeBSD. Those test failures kinda suggest that the CPython port for FreeBSD is currently failing FreeBSD, too. I promise that @beartype and FreeBSD will be best buddies sometime in 2024. Of course, I promise much and deliver even less. This must be why I live in a cottage in the Canadian wilderness. 🥲

Oh – and I have an obnoxious question. Clearly, you are the FreeBSD domain expert here. What's the easiest and sanest way to install different CPython versions (e.g., CPython 3.10, CPython 3.11) under FreeBSD? Would that be via the official Ports toolchain as well or would something like the third-party pyenv script be a better bet for that?

CPython 3.9 is great, but it would be even greater to test any potential resolution of these issues against CPython ≥ 3.10 as well.

@yurivict
Copy link
Author

Thank you!

@leycec
Copy link
Member

leycec commented Sep 23, 2023

You're too kind, @yurivict. No, seriously. It is dangerous to thank me too soon. I'll probably end up sidetracked with something completely unrelated and then shamefully forget all about this. Please prod me with a blunt stick if I don't do this by the end of the year. 🪵

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants