1. 22 Sep, 2020 6 commits
    • Kirill Smelkov's avatar
      pygolang v0.0.7 · 73fdea50
      Kirill Smelkov authored
      73fdea50
    • Kirill Smelkov's avatar
      gpython: Fix pymain to properly setup sys.path (take 2) · fb98e594
      Kirill Smelkov authored
      This continues 6b4990f6 (gpython: Fix pymain to properly setup
      sys.path[0]) - now we add test and verify that gpython actually sets
      sys.path in the same way as underlying python does:
      
      - don't add directory of gpython to sys.path
      - for `gpython file` add to sys.path[0] realpath(dir(file)) instead of
        dir(file)  (see PySys_SetArgvEx for the reference, and else - if we do
        not make this change - added test breaks)
      - for `gpython -m mod` add to sys.path[0] realpath('') instead of ''.
        This exactly matches PY3 behaviour, while PY2 behaviour is to add ''
        However PY3 behaviour
      
          * is more sane, and
          * fixes test_defer_excchain_traceback on py27-gevent
      
        -> so we stick to it.
      
      Now all tests pass again.
      fb98e594
    • Kirill Smelkov's avatar
      gpython: Preimport golang and gevent from exactly the same place as std python would do · 1f6f31cd
      Kirill Smelkov authored
      GPython preimports golang and gevent, but until now, it was preimporting
      them before adjusting sys.path according to given -c/-m/file/... And
      this was leading to difference in behaviour with standard Python where
      e.g. `import golang` might result in different files loaded if e.g.
      golang/ is there on cwd and -c/-m was given.
      
      -> Rework gpython startup so that golang/gevent preimport happens after
      sys.path initialization.
      
      This fixes `tox -e py27-gevent` which was previously failing on
      test_defer_excchain_dump_pytest / test_defer_excchain_dump_ipython
      because dumped paths were different than expected ones.
      
      It, however, breaks test_defer_excchain_traceback on py27-gevent.  ->
      We'll do more fixups to sys.path handling in the next patch which will
      fix that failure as well.
      1f6f31cd
    • Kirill Smelkov's avatar
      gpython: Move code to handle -V to "start interpreter" phase · 51925488
      Kirill Smelkov authored
      We'll need this in the next patch, where golang/gevent preimport will be
      moved from "before call to pymain", to "in between option parsing and
      interpreter start".
      51925488
    • Kirill Smelkov's avatar
      golang: tests: Fix Pytest integration wrt python3-dbg · a1ac2a45
      Kirill Smelkov authored
      There, with pytest 6.0.x, pytest emits its internal deprecation warning
      (the usage of deprecated attribute is inside pytest):
      
          .../_pytest/compat.py:340: PytestDeprecationWarning: The TerminalReporter.writer attribute is deprecated, use TerminalReporter._tw instead at your own risk.
          See https://docs.pytest.org/en/stable/deprecations.html#terminalreporter-writer for more information.
            return getattr(object, name, default)
      
      Which leads to test_defer_excchain_dump_pytest failure since this test
      verifies stderr to be empty:
      
              def test_defer_excchain_dump_pytest():
                  tbok = readfile(dir_testprog + "/golang_test_defer_excchain.txt-pytest")
                  retcode, stdout, stderr = _pyrun(["-m", "pytest", "-o", "python_functions=main",
                                              "--tb=short", "golang_test_defer_excchain.py"],
                                              cwd=dir_testprog, stdout=PIPE, stderr=PIPE)
                  assert retcode != 0, (stdout, stderr)
          >       assert stderr == b""
          E       AssertionError: assert b'/home/kirr/...e, default)\n' == b''
          E         Full diff:
          E         - b''
          E         + (
          E         +  b'/home/kirr/src/tools/go/py3dbg.venv/lib/python3.8/site-packages/_pytest/comp'
          E         +  b'at.py:340: PytestDeprecationWarning: The TerminalReporter.writer attribute i'
          E         +  b's deprecated, use TerminalReporter._tw instead at your own risk.\nSee htt'
          E         +  b'ps://docs.pytest.org/en/stable/deprecations.html#terminalreporter-writer for'...
          E
          E         ...Full output truncated (3 lines hidden), use '-vv' to show
      
      -> Fix it by not letting spawned pytest to emit deprecation warnings in that test.
      a1ac2a45
    • Kirill Smelkov's avatar
      gpython: Implement -W · a0016938
      Kirill Smelkov authored
      We'll need warnings control in the next patch to fix Pytest integration
      wrt python3-dbg with `-W ignore::DeprecationWarning`.
      a0016938
  2. 21 Sep, 2020 1 commit
    • Kirill Smelkov's avatar
      gpython: Reorganize options parsing · b47edf42
      Kirill Smelkov authored
      Reorganize parsiong of command line options so that first all options are
      parsed in a loop, and only after that a module/file/command is executed.
      
      This is needed as preparatory step for next patch: there we'll add
      support for -W, and `-W arg` can be given multiple times and has to be
      processed multiple times by creating multiple corresponding warning
      filters. Because those warning filters has to be applied uniformly to
      all 4 codepaths of execution phase (-m/-c/file/interactive console), it
      makes sense to move execution phase to after options parsing and inject
      common runtime preparatory steps right before that.
      
      This logic generally applies not only to -W, but to all other python
      options - e.g. -Q,-u,...
      b47edf42
  3. 18 Sep, 2020 3 commits
    • Kirill Smelkov's avatar
      golang: tests: Fix TSAN/ASAN wrt Debian testing · 49bb8dcd
      Kirill Smelkov authored
      Current Debian testing builds libtsan/libasan with --as-needed, which
      leads to libstdc++.so not being linked in. Compare Debian 10:
      
          kirr@link:~/src/tools/go/pygolang$ ldd /usr/lib/x86_64-linux-gnu/libasan.so.5
              linux-vdso.so.1 (0x00007ffe7e97f000)
              libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f00ad9d5000)
              librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f00ad9cb000)
              libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f00ad9aa000)
              libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f00ad7d2000)		<-- libstdc++
              libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f00ad64f000)
              libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f00ad48e000)
              libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f00ad472000)
              /lib64/ld-linux-x86-64.so.2 (0x00007f00ae7c8000)
      
      to Debian testing:
      
          kirr@deco:~/src/tools/go/pygolang$ ldd /usr/lib/x86_64-linux-gnu/libasan.so.6
              linux-vdso.so.1 (0x00007ffe15d0b000)
              libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f53ba069000)
              libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f53ba047000)
              libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f53b9f03000)
              libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f53b9d3e000)
              libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f53b9d24000)
              /lib64/ld-linux-x86-64.so.2 (0x00007f53baa6b000)
      
      where libstdc++ is not being linked to libasan.so
      
      This leads to the following crash:
      
          golang/golang_test.py::test_pyx_select_inplace ==181237==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_interceptors.cpp:333 "((__interception::real___cxa_throw)) != (0)" (0x0, 0x0)
              #0 0x7f76aa9f4657  (/usr/lib/x86_64-linux-gnu/libasan.so.6+0xb2657)
              #1 0x7f76aaa11d5a  (/usr/lib/x86_64-linux-gnu/libasan.so.6+0xcfd5a)
              #2 0x7f76aa97ac14 in __cxa_throw (/usr/lib/x86_64-linux-gnu/libasan.so.6+0x38c14)
              #3 0x7f76a497a9ef in panic golang/runtime/libgolang.cpp:79
              #4 0x7f76a497e9a9 in _chanselect golang/runtime/libgolang.cpp:956
              #5 0x7f76a455573c in select<1> golang/libgolang.h:535
              #6 0x7f76a454fa4b in _test_select_inplace() golang/runtime/libgolang_test.cpp:417
              #7 0x7f76a452781e in __pyx_pf_6golang_12_golang_test_30test_select_inplace golang/_golang_test.cpp:4859
              #8 0x7f76a45277db in __pyx_pw_6golang_12_golang_test_31test_select_inplace golang/_golang_test.cpp:4821
      
      explained by https://github.com/google/sanitizers/issues/934
      
      -> work it around by manually preloading libstdc++ as well.
      49bb8dcd
    • Kirill Smelkov's avatar
      golang: tests: Fix IPython integration test wrt TSAN/ASAN · b938af8b
      Kirill Smelkov authored
      test_defer_excchain_dump_ipython was setting fresh env anew, thus not
      propagating $LD_PRELOAD that trun sets when libgolang was built with
      thread or address sanitizer. This way the subprocess spawned for IPython
      was failing with e.g.
      
              ==152924==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
      
      -> Fix it by only adjusting environment for spawned IPython instead of
      setting it completely anew.
      
      Fixes: 09629367 (golang: tests: Add tests for IPython and Pytest
      integration patches)
      b938af8b
    • Kirill Smelkov's avatar
      golang: tests: Don't hide output details in assert on retcode of spawned command · 6e31304d
      Kirill Smelkov authored
      For example if test_defer_excchain_dump_ipython fails the output was:
      
          >       assert retcode == 0
          E       assert 1 == 0
      
      and it was unclear what was going on. Now the output is e.g.
      
          >       assert retcode == 0, (stdout, stderr)
          E       AssertionError: ('', '==152924==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
          E         ')
          E       assert 1 == 0
      
      Amends: 09629367 (golang: tests: Add tests for IPython and Pytest
      integration patches) and bb9a94c3 (golang: Teach defer to chain
      exceptions (PEP 3134) even on Python2).
      6e31304d
  4. 30 Jul, 2020 4 commits
    • Kirill Smelkov's avatar
      gpython: Add way to run it with threads runtime · a6b993c8
      Kirill Smelkov authored
      Until now gpython was always activating gevent on startup + adding
      goodness such as "always UTF-8 default encoding"; go, chan, b/u and
      friends available from builtin namespace, etc... While those goodness
      are sometimes useful on their own, it is not always appropriate to force
      a project to switch from threads to gevent.
      
      For this reason add a flag to select which runtime - either gevent
      or threads - gpython should use.
      
      	gpython -Xgpython.runtime=gevent	selects gevent,
      
      while
      
      	gpython -Xgpython.runtime=threads	selects threads.
      
      Gevent remains the default.
      
      It is also possible to specify desired runtime via $GPYTHON_RUNTIME
      environment variable.
      
      /reviewed-on nexedi/pygolang!5
      a6b993c8
    • Kirill Smelkov's avatar
      gpython: Reorganize main a bit · c0282565
      Kirill Smelkov authored
      Restructure code a bit to prepare it for the next patch.
      Plain code movement.
      
      /reviewed-on nexedi/pygolang!5
      c0282565
    • Kirill Smelkov's avatar
      gpython: Add support for -V / --version · 70c4c82f
      Kirill Smelkov authored
      On CPython:
      
      	$ python -V
      	Python 2.7.18
      
      	$ gpython -V
      	GPython 0.0.6.post2 [gevent 20.6.2] / CPython 2.7.18
      
      On PyPy:
      
      	$ python -V
              Python 3.6.9 (2ad108f17bdb, Apr 07 2020, 02:59:05)
              [PyPy 7.3.1 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]
      
      	$ gpython -V
      	GPython 0.0.6.post2 [gevent 20.5.0] / PyPy 7.3.1 / Python 3.6.9
      
      /reviewed-on nexedi/pygolang!5
      70c4c82f
    • Kirill Smelkov's avatar
      gpython: Support -c<command>, not only -c <command> · e6714e49
      Kirill Smelkov authored
      And same for -m<module> - becuase Python supports it this way.
      
      Before the patch:
      
      	$ python '-cprint "hello world"'
      	hello world
      	$ gpython '-cprint "hello world"'
      	unknown option: '-cprint "hello world"'
      
      After the patch:
      
      	$ python '-cprint "hello world"'
      	hello world
      	$ gpython '-cprint "hello world"'
      	hello world
      
      /reviewed-on nexedi/pygolang!5
      e6714e49
  5. 07 Jul, 2020 3 commits
  6. 29 May, 2020 1 commit
    • Kirill Smelkov's avatar
      gpython: Include gevent version into banner · 0e3da017
      Kirill Smelkov authored
      Gevent is major component gpython builds on - it deserves to be included
      into version and is handy to know if one hits a bug with gpython - to
      see in which particular runtime environment the bug was hit.
      
      Before:
      
          $ gpython
          Python 3.7.3 (default, Dec 20 2019, 18:57:59)
          [GCC 8.3.0] [GPython 0.0.6.post2] on linux
          Type "help", "copyright", "credits" or "license" for more information.
          (InteractiveConsole)
          >>>
      
      After:
      
          $ gpython
          Python 3.7.3 (default, Dec 20 2019, 18:57:59)
          [GCC 8.3.0] [GPython 0.0.6.post2] [gevent 20.5.1] on linux
          Type "help", "copyright", "credits" or "license" for more information.
          (InteractiveConsole)
          >>>
      
      /cc @gabriel, @jerome
      /proposed-for-review-on: nexedi/pygolang!4
      0e3da017
  7. 21 May, 2020 2 commits
  8. 20 May, 2020 1 commit
  9. 19 May, 2020 4 commits
    • Kirill Smelkov's avatar
      golang: tests: Add tests for IPython and Pytest integration patches · 09629367
      Kirill Smelkov authored
      bb9a94c3 (golang: Teach defer to chain exceptions (PEP 3134) even on
      Python2) added integration patches for IPython and Pytest to properly
      dump tracebacks for chained exceptions even on Python2. However the
      functionality of patches was tested only manually.
      
      -> Add corresponding tests to verify how IPython and Pytest behaves
      when dumping tracebacks.
      09629367
    • Kirill Smelkov's avatar
      golang: tests: assertDoc: Include ~/... into PYGOLANG normalization · 42ab98a6
      Kirill Smelkov authored
      assertDoc normalizes paths in compared texts with the idea for etalon
      output to contain PYGOLANG instead of whatever actual path there will be
      when testing the package. This already works.
      
      However IPython, when dumping tracebacks, tries to shorten paths and
      abbreviate $HOME with ~ in them. This breaks normalization which misses
      to convert prefix of those paths into PYGOLANG.
      
      -> Fix it by teaching assertDoc to also handle paths that start with ~
      and correctly normalize them.
      
      This will be needed in the next patch where we will add tests for how
      ipython and pytest dump tracebacks for chained exceptions.
      42ab98a6
    • Kirill Smelkov's avatar
      golang: tests: Factor file-reading into readfile() utility · 2413b5ba
      Kirill Smelkov authored
      We are going to use it from several places.
      2413b5ba
    • Kirill Smelkov's avatar
      golang: tests: Factor-out path to directories into global dir_* variable · 0148cb89
      Kirill Smelkov authored
      Paths to the directories are already used in several functions, and are
      going to be used more. Move them to common place to avoid duplication.
      0148cb89
  10. 03 May, 2020 2 commits
    • Kirill Smelkov's avatar
      pyx.build: Fix it on macOS (v↑ setuptools_dso (1.4 -> 1.6)) · fb662979
      Kirill Smelkov authored
      Starting from setuptools-dso 1.6 pyx.build no longer fails on macOS due to:
      
        https://github.com/mdavidsaver/setuptools_dso/commit/dd2cf303
        https://github.com/mdavidsaver/setuptools_dso/commit/6883d6dc
        https://github.com/mdavidsaver/setuptools_dso/commit/78ae8852
        https://github.com/mdavidsaver/setuptools_dso/pull/9
        https://github.com/mdavidsaver/setuptools_dso/issues/8
      
      It was previously failing with setuptools-dso==1.5:
      
        (py3.venv) kirr@Kirills-iMac pygolang % python -m pytest
        ==================================== test session starts =====================================
        platform darwin -- Python 3.7.6, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
        rootdir: /Users/kirr/pygolang
        collected 100 items
      
        golang/_gopath_test.py ..                                                              [  2%]
        golang/context_test.py ..                                                              [  4%]
        golang/cxx_test.py ..                                                                  [  6%]
        golang/errors_test.py ........                                                         [ 14%]
        golang/fmt_test.py ...                                                                 [ 17%]
        golang/golang_test.py .............................................                    [ 62%]
        golang/io_test.py .                                                                    [ 63%]
        golang/strconv_test.py ..                                                              [ 65%]
        golang/strings_test.py .....                                                           [ 70%]
        golang/sync_test.py .............                                                      [ 83%]
        golang/time_test.py ........                                                           [ 91%]
        golang/pyx/build_test.py FF.                                                           [ 94%]
        golang/pyx/runtime_test.py .                                                           [ 95%]
        gpython/gpython_test.py ssss.                                                          [100%]
      
        ========================================== FAILURES ==========================================
        _______________________________________ test_pyx_build _______________________________________
      
            def test_pyx_build():
                pyxuser = testprog + "/golang_pyx_user"
                pyrun(["setup.py", "build_ext", "-i"], cwd=pyxuser)
      
                # run built test.
                _ = pyout(["-c",
                    # XXX `import golang` is a hack: it dynamically loads _golang.so -> libgolang.so,
                    # and this way dynamic linker already has libgolang.so DSO found and in
                    # memory for all further imports. If we don't, current state of setuptools_dso
                    # is that `import pyxuser.test` will fail finding libgolang.so.
                    "import golang;" +
        >           "from pyxuser import test; test.main()"], cwd=pyxuser)
      
        golang/pyx/build_test.py:40:
        _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
        golang/golang_test.py:1709: in pyout
            return pyrun(argv, stdin=stdin, stdout=stdout, stderr=stderr, **kw)
        _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
      
        argv = ['-c', 'import golang;from pyxuser import test; test.main()'], stdin = None, stdout = b'', stderr = None
        kw = {'cwd': '/Users/kirr/pygolang/golang/pyx/testprog/golang_pyx_user'}, retcode = 1
      
            def pyrun(argv, stdin=None, stdout=None, stderr=None, **kw):
                retcode, stdout, stderr = _pyrun(argv, stdin=stdin, stdout=stdout, stderr=stderr, **kw)
                if retcode:
        >           raise RuntimeError(' '.join(argv) + '\n' + (stderr and str(stderr) or '(failed)'))
        E           RuntimeError: -c import golang;from pyxuser import test; test.main()
        E           (failed)
      
        golang/golang_test.py:1703: RuntimeError
        ------------------------------------ Captured stdout call ------------------------------------
        running build_ext
        cythoning pyxuser/test.pyx to pyxuser/test.cpp
        building 'pyxuser.test' extension
        creating build
        creating build/temp.macosx-10.15-x86_64-3.7
        creating build/temp.macosx-10.15-x86_64-3.7/pyxuser
        clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -I/Users/kirr/pygolang -I/Users/kirr/py3.venv/bin/../include/site/python3.7 -I/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c pyxuser/test.cpp -o build/temp.macosx-10.15-x86_64-3.7/pyxuser/test.o -std=c++11 -fno-strict-aliasing
        creating build/lib.macosx-10.15-x86_64-3.7
        creating build/lib.macosx-10.15-x86_64-3.7/pyxuser
        clang++ -bundle -undefined dynamic_lookup build/temp.macosx-10.15-x86_64-3.7/pyxuser/test.o -L/Users/kirr/pygolang/golang/runtime -llibgolang -o build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so
        otool -L build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so
        build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so:
        	@loader_path/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        install_name_tool -change @loader_path/liblibgolang.0.1.dylib @loader_path/../golang/runtime/liblibgolang.0.1.dylib build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so
        otool -L build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so
        build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so:
        	@loader_path/../golang/runtime/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        copying build/lib.macosx-10.15-x86_64-3.7/pyxuser/test.cpython-37m-darwin.so -> pyxuser
        ------------------------------------ Captured stderr call ------------------------------------
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
        ImportError: dlopen(/Users/kirr/pygolang/golang/pyx/testprog/golang_pyx_user/pyxuser/test.cpython-37m-darwin.so, 2): Library not loaded: @loader_path/../golang/runtime/liblibgolang.0.1.dylib
          Referenced from: /Users/kirr/pygolang/golang/pyx/testprog/golang_pyx_user/pyxuser/test.cpython-37m-darwin.so
          Reason: image not found
        _______________________________________ test_dso_build _______________________________________
      
            def test_dso_build():
                dsouser = testprog + "/golang_dso_user"
                pyrun(["setup.py", "build_dso", "-i"], cwd=dsouser)
                pyrun(["setup.py", "build_ext", "-i"], cwd=dsouser)
      
                # run built test.
                _ = pyout(["-c",
                    # XXX `import golang` is a hack - see test_pyx_build for details.
                    "import golang;" +
        >           "from dsouser import test; test.main()"], cwd=dsouser)
      
        golang/pyx/build_test.py:54:
        _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
        golang/golang_test.py:1709: in pyout
            return pyrun(argv, stdin=stdin, stdout=stdout, stderr=stderr, **kw)
        _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
      
        argv = ['-c', 'import golang;from dsouser import test; test.main()'], stdin = None, stdout = b'', stderr = None
        kw = {'cwd': '/Users/kirr/pygolang/golang/pyx/testprog/golang_dso_user'}, retcode = 1
      
            def pyrun(argv, stdin=None, stdout=None, stderr=None, **kw):
                retcode, stdout, stderr = _pyrun(argv, stdin=stdin, stdout=stdout, stderr=stderr, **kw)
                if retcode:
        >           raise RuntimeError(' '.join(argv) + '\n' + (stderr and str(stderr) or '(failed)'))
        E           RuntimeError: -c import golang;from dsouser import test; test.main()
        E           (failed)
      
        golang/golang_test.py:1703: RuntimeError
        ------------------------------------ Captured stdout call ------------------------------------
        running build_dso
        Building DSOs
        building 'dsouser.dso' DSO as build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib
        creating build
        creating build/temp.macosx-10.15-x86_64-3.7
        creating build/temp.macosx-10.15-x86_64-3.7/dsouser
        clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -I/Users/kirr/pygolang -c dsouser/dso.cpp -o build/temp.macosx-10.15-x86_64-3.7/dsouser/dso.o -std=c++11 -fno-strict-aliasing
        creating build/lib.macosx-10.15-x86_64-3.7
        creating build/lib.macosx-10.15-x86_64-3.7/dsouser
        clang++ -dynamiclib -undefined dynamic_lookup build/temp.macosx-10.15-x86_64-3.7/dsouser/dso.o -L/Users/kirr/pygolang/golang/runtime -llibgolang -o build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib -install_name @loader_path/libdso.dylib
        otool -L build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib
        build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib:
        	@loader_path/libdso.dylib (compatibility version 0.0.0, current version 0.0.0)
        	@loader_path/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        install_name_tool -change @loader_path/liblibgolang.0.1.dylib @loader_path/../golang/runtime/liblibgolang.0.1.dylib build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib
        otool -L build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib
        build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib:
        	@loader_path/libdso.dylib (compatibility version 0.0.0, current version 0.0.0)
        	@loader_path/../golang/runtime/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        copying build/lib.macosx-10.15-x86_64-3.7/dsouser/libdso.dylib -> dsouser
        running build_ext
        cythoning dsouser/test.pyx to dsouser/test.cpp
        building 'dsouser.test' extension
        clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -I/Users/kirr/pygolang -I/Users/kirr/py3.venv/bin/../include/site/python3.7 -I/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c dsouser/test.cpp -o build/temp.macosx-10.15-x86_64-3.7/dsouser/test.o -std=c++11 -fno-strict-aliasing
        clang++ -bundle -undefined dynamic_lookup build/temp.macosx-10.15-x86_64-3.7/dsouser/test.o -L/Users/kirr/pygolang/golang/runtime -Lbuild/lib.macosx-10.15-x86_64-3.7/dsouser -llibgolang -ldso -o build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so
        otool -L build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so
        build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so:
        	@loader_path/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	@loader_path/libdso.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        install_name_tool -change @loader_path/liblibgolang.0.1.dylib @loader_path/../golang/runtime/liblibgolang.0.1.dylib build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so
        install_name_tool -change @loader_path/libdso.dylib @loader_path/./libdso.dylib build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so
        otool -L build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so
        build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so:
        	@loader_path/../golang/runtime/liblibgolang.0.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        	@loader_path/./libdso.dylib (compatibility version 0.0.0, current version 0.0.0)
        	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
        	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
        copying build/lib.macosx-10.15-x86_64-3.7/dsouser/test.cpython-37m-darwin.so -> dsouser
        ------------------------------------ Captured stderr call ------------------------------------
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
        ImportError: dlopen(/Users/kirr/pygolang/golang/pyx/testprog/golang_dso_user/dsouser/test.cpython-37m-darwin.so, 2): Library not loaded: @loader_path/../golang/runtime/liblibgolang.0.1.dylib
          Referenced from: /Users/kirr/pygolang/golang/pyx/testprog/golang_dso_user/dsouser/test.cpython-37m-darwin.so
          Reason: image not found
        ========================== 2 failed, 94 passed, 4 skipped in 20.26s ==========================
      fb662979
    • Kirill Smelkov's avatar
      golang: Teach qq to be usable with both bytes and str format whatever type qq argument is · edc7aaab
      Kirill Smelkov authored
      qq is used to quote strings or byte-strings. The following example
      illustrates the problem we are currently hitting in zodbtools with
      Python3:
      
          >>> "hello %s" % qq("мир")
          'hello "мир"'
      
          >>> b"hello %s" % qq("мир")
          Traceback (most recent call last):
            File "<stdin>", line 1, in <module>
          TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'
      
          >>> "hello %s" % qq(b("мир"))
          'hello "мир"'
      
          >>> b"hello %s" % qq(b("мир"))
          Traceback (most recent call last):
            File "<stdin>", line 1, in <module>
          TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'
      
      i.e. one way or another if type of format string and what qq returns do not
      match it creates a TypeError.
      
      We want qq(obj) to be useable with both string and bytestring format.
      
      For that let's teach qq to return special str- and bytes- derived types that
      know how to automatically convert to str->bytes and bytes->str via b/u
      correspondingly. This way formatting works whatever types combination it was
      for format and for qq, and the whole result has the same type as format.
      
      For now we teach only qq to use new types and don't generally expose
      _str and _unicode to be returned by b and u yet. However we might do so
      in the future after incrementally gaining a bit more experience.
      
      /proposed-for-review-on: nexedi/pygolang!1
      edc7aaab
  11. 29 Apr, 2020 3 commits
  12. 16 Apr, 2020 3 commits
    • Kirill Smelkov's avatar
      pygolang v0.0.6.post2 · 283a1558
      Kirill Smelkov authored
      A build fix wrt gevent-1.5 + benchmarks for nogil go and channels.
      283a1558
    • Kirill Smelkov's avatar
      Fix build for gevent-1.5 · 4d667fa3
      Kirill Smelkov authored
      Starting from gevent >= 1.5 '*.pxd' files for gevent API are no longer
      provided, at least in released gevent wheels. This broke pygolang:
      
          Error compiling Cython file:
          ------------------------------------------------------------
          ...
      
          # Gevent runtime uses gevent's greenlets and semaphores.
          # When sema.acquire() blocks, gevent switches us from current to another greenlet.
      
          IF not PYPY:
              from gevent._greenlet cimport Greenlet
             ^
          ------------------------------------------------------------
      
          golang/runtime/_runtime_gevent.pyx:28:4: 'gevent/_greenlet.pxd' not found
      
      Since gevent upstream refuses to restore Cython level access[1], let's fix the
      build by using gevent bits via Python-level.
      
      Even when used via py import gevent-1.5 brings speed improvement compared to
      gevent-1.4 (used via cimport):
      
      	(on i7@2.6GHz, gevent runtime)
      
                            gevent-1.4   gevent-1.5
                            (cimport)    (py import)
      
          name              old time/op  new time/op  delta
          pyx_select_nogil  9.47µs ± 0%  8.74µs ± 0%   -7.70%  (p=0.000 n=10+9)
          pyx_go_nogil      14.3µs ± 1%  12.0µs ± 1%  -16.52%  (p=0.000 n=10+10)
          pyx_chan_nogil    7.10µs ± 1%  6.32µs ± 1%  -10.89%  (p=0.000 n=10+10)
          go                16.0µs ± 2%  13.4µs ± 1%  -16.37%  (p=0.000 n=10+10)
          chan              7.50µs ± 0%  6.79µs ± 0%   -9.53%  (p=0.000 n=10+10)
          select            10.8µs ± 1%  10.0µs ± 1%   -6.78%  (p=0.000 n=10+10)
      
      Using gevent-1.5 could have been even faster via cimport (it is still
      possible to compile and test against gevent installed in development
      mode via `pip install -e` because pxd files are there in gevent worktree
      and tarball):
      
                            gevent-1.5   gevent-1.5
                            (py import)  (cimport)
      
          name              old time/op  new time/op  delta
          pyx_select_nogil  8.74µs ± 0%  7.90µs ± 1%  -9.60%  (p=0.000 n=9+10)
          pyx_go_nogil      12.0µs ± 1%  11.2µs ± 2%  -6.35%  (p=0.000 n=10+10)
          pyx_chan_nogil    6.32µs ± 1%  5.89µs ± 0%  -6.80%  (p=0.000 n=10+9)
          go                13.4µs ± 1%  12.4µs ± 1%  -7.54%  (p=0.000 n=10+9)
          chan              6.79µs ± 0%  6.42µs ± 0%  -5.47%  (p=0.000 n=10+10)
          select            10.0µs ± 1%   9.4µs ± 1%  -6.39%  (p=0.000 n=10+10)
      
      but we cannot use cimport to access gevent-1.5 universally, since pxd are not
      shipped in gevent wheel releases.
      
      In the future we might want to change plain version check into compile time
      check whether gevent/_greenlet.pxd is actually present or not and use faster
      access if yes. Requesting gevent to be installed in non-binary form
      might be also an option worth trying.
      
      However plain version check should be ok for now.
      
      [1] https://github.com/gevent/gevent/issues/1568
      4d667fa3
    • Kirill Smelkov's avatar
      golang: Add benchmarks for nogil go and channels · 2114a560
      Kirill Smelkov authored
      on i7@2.6GHz it looks like:
      
      thread runtime:
      
          name              time/op
          pyx_select_nogil  2.70µs ±13%
          pyx_go_nogil      15.9µs ± 1%
          pyx_chan_nogil    2.79µs ± 2%
          go                17.6µs ± 0%
          chan              3.05µs ± 4%
          select            3.62µs ± 4%
      
      gevent runtime (gevent-1.4.0):
      
          name              time/op
          pyx_select_nogil  9.39µs ± 1%
          pyx_go_nogil      15.1µs ± 2%
          pyx_chan_nogil    7.10µs ± 1%
          go                16.6µs ± 1%
          chan              7.47µs ± 1%
          select            10.7µs ± 0%
      2114a560
  13. 15 Apr, 2020 1 commit
  14. 05 Mar, 2020 1 commit
  15. 28 Feb, 2020 4 commits
    • Kirill Smelkov's avatar
      pygolang v0.0.6 · 5e1cb5ea
      Kirill Smelkov authored
      5e1cb5ea
    • Kirill Smelkov's avatar
      strconv: Fix b & friends on macos/windows · 0561926a
      Kirill Smelkov authored
      On macos and windows, Python2 is built with --enable-unicode=ucs2, which
      makes it to use UTF-16 encoding for unicode characters, and so for
      characters higher than U+10000 it uses surrogate encoding with _2_
      unicode points, for example:
      
              >>> import sys
              >>> sys.maxunicode
              65535                       <-- NOTE indicates UCS2 build
              >>> s = u'\U00012345'
              >>> s
              u'\U00012345'
              >>> s.encode('utf-8')
              '\xf0\x92\x8d\x85'
              >>> len(s)
              2                           <-- NOTE _not_ 1
              >>> s[0]
              u'\ud808'
              >>> s[1]
              u'\udf45'
      
      This leads to e.g. b tests failing for
      
          # tbytes                        tunicode
          (b"\xf0\x90\x8c\xbc",           u'\U0001033c'),     # Valid 4 Octet Sequence '𐌼'
      
          >           assert b(tunicode) == tbytes
          E           AssertionError: assert '\xed\xa0\x80\xed\xbc\xbc' == '\xf0\x90\x8c\xbc'
          E             - \xed\xa0\x80\xed\xbc\xbc
          E             + \xf0\x90\x8c\xbc
      
      because on UCS2 python build u'\U0001033c' is represented as 2 unicode
      points:
      
          >>> s = u'\U0001033c'
          >>> len(s)
          2
          >>> s[0]
          u'\ud800'
          >>> s[1]
          u'\udf3c'
          >>> s[0].encode('utf-8')
          '\xed\xa0\x80'
          >>> s[1].encode('utf-8')
          '\xed\xbc\xbc'
      
      -> Fix it by detecting UCS2 build and working around by manually
      combining such surrogate unicode pairs appropriately.
      
      A reference on the subject:
      
      https://matthew-brett.github.io/pydagogue/python_unicode.html#utf-16-ucs2-builds-of-python-and-32-bit-unicode-code-points
      0561926a
    • Kirill Smelkov's avatar
      strconv: Switch _utf8_decode_rune to return rune ordinal instead of unicode character · 5cc679ac
      Kirill Smelkov authored
      This is a preparatory step for the next patch where we'll be fixing
      strconv for Python2 builds with --enable-unicode=ucs2, where a unicode
      character can be taking _2_ unicode points.
      
      In that general case relying on unicode objects to represent runes is
      not good, because many things generally do not work for U+10000 and
      above, e.g. ord breaks:
      
          >>> import sys
          >>> sys.maxunicode
          65535                       <-- NOTE indicates UCS2 build
          >>> s = u'\U00012345'
          >>> s
          u'\U00012345'
          >>> s.encode('utf-8')
          '\xf0\x92\x8d\x85'
          >>> len(s)
          2                           <-- NOTE _not_ 1
          >>> ord(s)
          Traceback (most recent call last):
            File "<stdin>", line 1, in <module>
          TypeError: ord() expected a character, but string of length 2 found
      
      so we switch to represent runes as integer, similarly to what Go does.
      5cc679ac
    • Kirill Smelkov's avatar
      pyx.build: Fix hang under gpython · cd67996e
      Kirill Smelkov authored
      Commit 8af78fc5 (pyx.build: v↑ setuptools_dso (1.2 -> 1.4)) upgraded
      setuptools_dso to 1.4, but since from
      
      https://github.com/mdavidsaver/setuptools_dso/commit/3f3ff746
      
      setuptools_dso started to use multiprocessing, pyx.build, when running
      under gpython, started to hang, which is a known gevent problem - see
      e.g. here: https://github.com/gevent/gevent/issues/993. The problem was
      manifesting itself as pyx.build unit test hanging under Python3.
      
      Fix it by installing gevent multiprocessing plugin which is
      automatically used/activated by gevent.monkey.patch_all().
      
      geventmp says it is pre-alpha, but by using it we can unhang pyx.build
      tests, which is better state than before. The other future possibility
      would be to use https://github.com/jgehrcke/gipc wrapped into
      multiprocessing compatible API.
      cd67996e
  16. 27 Feb, 2020 1 commit