- 26 Jan, 2022 12 commits
-
-
Kirill Smelkov authored
Provide os/signal package that can be used to setup signal delivery to nogil channels. This way for user code signal handling becomes regular handling of a signalling channel instead of being something special or limited to only-main python thread. The rationale for why we need it is explained below: There are several problems with regular python's stdlib signal module: 1. Python2 does not call signal handler from under blocked lock.acquire. This means that if the main thread is blocked waiting on a semaphore, signal delivery will be delayed indefinitely, similarly to e.g. problem described in nxdtest!14 (comment 147527) where raising KeyboardInterrupt is delayed after SIGINT for many, potentially unbounded, seconds until ~semaphore wait finishes. Note that Python3 does not have this problem wrt stdlib locks and semaphores, but read below for the next point. 2. all pygolang communication operations (channels send/recv, sync.Mutex, sync.RWMutex, sync.Sema, sync.WaitGroup, sync.WorkGroup, ...) run with GIL released, but if blocked do not handle EINTR and do not schedule python signal handler to run (on main thread). Even if we could theoretically adjust this behaviour of pygolang at python level to match Python3, there are also C++ and pyx/nogil worlds. And we want gil and nogil worlds to interoperate (see https://pypi.org/project/pygolang/#cython-nogil-api), so that e.g. if completely nogil code happens to run on the main thread, signal handling is still possible, even if that signal handling was setup at python level. With signals delivered to nogil channels both nogil world and python world can setup signal handlers and to be notified of them irregardles of whether main python thread is currently blocked in nogil wait or not. /reviewed-on !17
-
Kirill Smelkov authored
To convert an object to str of current python. It will be handy to use __pystr when implementing __str__ methods. /reviewed-on !17
-
Kirill Smelkov authored
Provide C++ package "os" with File, Pipe, etc similarly to what is provided on Go side. The package works through IO methods provided by runtimes. We need IO facility because os/signal package will need to use pipe in cooperative IO mode in its receiving-loop goroutine. os.h and os.cpp are based on drafts from wendelin.core: https://lab.nexedi.com/nexedi/wendelin.core/blob/wendelin.core-2.0.alpha1-18-g38dde766/wcfs/client/wcfs_misc.h https://lab.nexedi.com/nexedi/wendelin.core/blob/wendelin.core-2.0.alpha1-18-g38dde766/wcfs/client/wcfs_misc.cpp /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
Else as https://github.com/python-greenlet/greenlet/pull/285 demonstrates there can be segmentation faults and crashes due to exceptions from one greenlet propagating to C stack of another greenlet. No test here. I've tried to do it, but with gevent (contrary to plain greenlets), spawning new task only schedules corresponding greenlet to run in the end of current event loop cycle instead of switching to created greenlet immediately. With this delaying, it was hard for me to develop corresponding test in a reasonable time. Hopefully having the test I've done for greenlet itself + hereby protection is good enough. /reviewed-on !17
-
Kirill Smelkov authored
This package provides special kind of atomic that is automatically reset to zero after fork in child. This kind of atomic will be used in os package to implement IO that does not deadlock in Close after fork. /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
This package provides wrappers to OS system calls. Minimal functionality that will be used to implement os and os/signal pacakges. /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
Package os will need to access runtime operations to implement IO. /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
We will soon need to use common functionality(*) from both runtimes and other packages. The "other packages" are all C++ and it is handy to keep common functionality in C++ as well. While we could also maintain `extern "C"` interface, it duplicates the work. Let's switch everything to C++ to ease further maintenance. (*) e.g. package internal/syscall from both runtimes and from package os. /reviewed-on !17
-
Kirill Smelkov authored
Without defined std::hash it is not possible to use channels as keys in dict or set. We will be using set<chan> in os/signal package implementation. /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
I forgot to include it in ad00be70 (libgolang: Introduce runtimes). /reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
/reviewed-on nexedi/pygolang!17
-
Kirill Smelkov authored
$ check-manifest lists of files in version control and sdist do not match! missing from sdist: .nxdtest /reviewed-on nexedi/pygolang!17
-
- 08 Dec, 2021 5 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
See https://foss.heptapod.net/pypy/pypy/-/issues/3610 for stdin case. -m started to behave as CPython.
-
Kirill Smelkov authored
On py3 'ps1' and b'ps1' are different keys and it was failing on PyPy3 as follows: # -i after stdin (also tests interactive mode as -i forces interactive even on non-tty) d = { b'hellopy': b(hellopy), b'ps1': b'' # cpython emits prompt to stderr } if is_pypy and not is_gpython: d['ps1'] = b'>>>> ' # native pypy emits prompt to stdout and >>>> instead of >>> _ = pyout(['-i'], stdin=b'import hello\n', cwd=testdata) > assert _ == b"%(ps1)shello\nworld\n['']\n%(ps1)s" % d E assert b">>>> hello\...\n['']\n>>>> " == b"hello\nworld\n['']\n" E At index 0 diff: b'>' != b'h' E Full diff: E - b"hello\nworld\n['']\n" E + b">>>> hello\nworld\n['']\n>>>> " E ? +++++ +++++ gpython/gpython_test.py:200: AssertionError Fix it. Amends e205dbf6 (gpython: Implement -i (interactive inspect after program run) + promised interactive-mode tests)
-
Kirill Smelkov authored
When _BaseCtx is setting up cancel propagation it locks a parent, checks for parent.err != nil, and, if it is, calls ctx._cancel(parent.err) _with_ _holding_ parent.mu. Since _cancel internally also goes through parents and locks them, this was deadlocking on the second call to parent.mu.lock(). -> Fix it by calling ctx._cancel(err) in the constructor outside of parent lock. The bug was there from the beginning - from e9567c7b (context: New package that mirrors Go's context). /trusted-by @jerome /reviewed-on nexedi/pygolang!16
-
Kirill Smelkov authored
- _propagateCancel is used only in _BaseCtx constructor -> inline it there. Being run in the constructor makes it clear that this code works on new _BaseCtx object with empty set of children. - since _cancelFrom interacts with the code moved from _propagateCancel, also move it to be close to cancel propagation setup. No functional changes, just plain code movement. /trusted-by @jerome /reviewed-on nexedi/pygolang!16
-
- 16 Aug, 2021 1 commit
-
-
Kirill Smelkov authored
The function that verifies "no exception/panic" case was prepared but not called at all. This oversight was there from 5146eb0b "Add support for defer & recover".
-
- 07 Apr, 2021 5 commits
-
-
Kirill Smelkov authored
/reviewed-by @jerome /reviewed-on nexedi/pygolang!15
-
Kirill Smelkov authored
Because else sys.modules['__main__'] points to the module of gpython itself, not user program. This difference can be important when e.g. user defines classes in main module and tries to pickle them. Such pickling will fail if gpython is not careful to run user's code in its own main. Without this patch added test fails as File "check_main.py", line 51, in <module> main() File "check_main.py", line 39, in main assert hasattr(mainmod, 'MyUniqueClassXYZ'), dir(mainmod) AssertionError: ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'main'] The problem was discovered while trying to run test program from https://github.com/zopefoundation/ZEO/issues/166 : $ gpython zopenrace-zeo.py Traceback (most recent call last): File "/home/kirr/tmp/trashme/Z/py2.venv/bin/gpython", line 8, in <module> sys.exit(main()) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/gpython/__init__.py", line 395, in main pymain(argv, init) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/gpython/__init__.py", line 266, in pymain run() File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/gpython/__init__.py", line 172, in run _execfile(filepath, g) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/gpython/__init__.py", line 275, in _execfile six.exec_(code, globals, locals) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/six.py", line 719, in exec_ exec("""exec _code_ in _globs_, _locs_""") File "<string>", line 1, in <module> File "zopenrace-zeo.py", line 205, in <module> main() File "zopenrace-zeo.py", line 190, in main init() File "zopenrace-zeo.py", line 126, in init transaction.commit() File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_manager.py", line 257, in commit return self.manager.commit() File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_manager.py", line 134, in commit return self.get().commit() File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 282, in commit reraise(t, v, tb) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 273, in commit self._commitResources() File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 456, in _commitResources reraise(t, v, tb) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/transaction/_transaction.py", line 430, in _commitResources rm.commit(self) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/ZODB/Connection.py", line 497, in commit self._commit(transaction) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/ZODB/Connection.py", line 546, in _commit self._store_objects(ObjectWriter(obj), transaction) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/ZODB/Connection.py", line 578, in _store_objects p = writer.serialize(obj) # This calls __getstate__ of obj File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/ZODB/serialize.py", line 430, in serialize return self._dump(meta, obj.__getstate__()) File "/home/kirr/tmp/trashme/Z/py2.venv/lib/python2.7/site-packages/ZODB/serialize.py", line 439, in _dump self._p.dump(state) PicklingError: Can't pickle <class '__main__.PInt'>: attribute lookup __main__.PInt failed /reviewed-by @jerome /reviewed-on !15
-
Kirill Smelkov authored
To match python behaviour: $ python >/dev/null Python 2.7.18 (default, Apr 20 2020, 20:30:41) [GCC 9.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 1+1 # NOTE the prompt (printed to stderr) $ python 2>/dev/null >>> 1+1 # NOTE the prompt (printed to stdout) Tests pending. /reviewed-by @jerome /reviewed-on !15
-
Kirill Smelkov authored
Not through interactive console, because it was printing prompts, while `python <prog.py` does not emit anything: $ cat prog.py print 'Hello World' $ python <prog.py Hello World $ gpython <prog.py Python 2.7.18 (default, Apr 20 2020, 20:30:41) [GCC 9.3.0] [GPython 0.0.8] [gevent 20.9.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) Hello World After the patch gpython output is the same as of python: $ gpython <prog.py Hello World Test coverage for interactive mode is pending. We'll add them soon in a follow-up patch after implementing -i. For _interact - by this patch logic - we should be dropping custom raw_input, since now _interact is called only when sys.stdin is tty. But we'll soon be invoking _interact when stdin is not a tty (for `gpython -i <prog.py`), so leave that logic in place as is. /reviewed-by @jerome /reviewed-on nexedi/pygolang!15
-
Kirill Smelkov authored
We will soon need this to be run from several places when implementing support for -i. /reviewed-by @jerome /reviewed-on nexedi/pygolang!15
-
- 26 Mar, 2021 1 commit
-
-
Kirill Smelkov authored
setuptools_dso 2 started to emit those autogenerated files. See https://github.com/mdavidsaver/setuptools_dso/pull/15 for details.
-
- 16 Mar, 2021 1 commit
-
-
Kirill Smelkov authored
Those are quote codes that Go strconv.Quote might produce. And even though Python does not use them when quoting, it too handles those quote codes when decoding: In [1]: '\r' Out[1]: '\r' In [2]: '\a\b\v\f' Out[2]: '\x07\x08\x0b\x0c' https://github.com/python/cpython/blob/2.7.18-0-g8d21aa21f2c/Objects/stringobject.c#L677-L688 -> Teach strconv.unquote + friends to handle them as well. /reviewed-by @jerome /reviewed-on nexedi/pygolang!14
-
- 14 Dec, 2020 2 commits
-
-
Kirill Smelkov authored
https://bugs.python.org/issue20443 This broke test_defer_excchain_dump because testprog/golang_test_defer_excchain.txt is prepared with output where `python file` shows that file name in traceback as it was specified on the command line, e.g. .../pygolang/golang/testprog$ python golang_test_defer_excchain.py Traceback (most recent call last): File ".../pygolang/golang/__init__.py", line 103, in _ return f(*argv, **kw) File "golang_test_defer_excchain.py", line 42, in main raise RuntimeError("err") RuntimeError: err while with py39 it became .../pygolang/golang/testprog$ python golang_test_defer_excchain.py Traceback (most recent call last): File ".../pygolang/golang/__init__.py", line 103, in _ return f(*argv, **kw) File ".../pygolang/golang/testprog/golang_test_defer_excchain.py", line 42, in main raise RuntimeError("err") RuntimeError: err (notice the difference related to "line 42") -> Fix it: - amend the test to conditionally prefix golang_test_defer_excchain.py in expected output with PYGOLANG/golang/testprog/ if it is Python >= 3.9. - amend `gpython file` to match behaviour of underlying `python file`, so that the test passes unconditionally whether it is run by python or gpython. -------- @jerome also says (nexedi/pygolang!13 (comment 122826)): FYI, buildout (and many zope packages) essentially use doctests for testing and they had to deal with similar differences in output. `zope.testing` comes with a doctest checker named "renormalizing" which normalize output with regular expressions, see for example setup of some buildout test [here](https://github.com/buildout/buildout/blob/db3d6e2fbf5d7ff2cc4b2507253c7a221cfc3e32/src/zc/buildout/tests.py#L3615-L3651). We definitely don't need this here for the moment, but maybe one day it can be useful. /reviewed-on nexedi/pygolang!13
-
Kirill Smelkov authored
Debian testing recently switched default python3 to be python3.9. Let's make sure pygolang works with that python version. Currently some tests fail - this will be addressed in the next patch. /reviewed-on nexedi/pygolang!13
-
- 11 Dec, 2020 2 commits
-
-
Kirill Smelkov authored
So that it becomes possible to write with WorkGroup(ctx) as wg: wg.go(f1) wg.go(f2) instead of wg = WorkGroup(ctx) defer(wg.wait) wg.go(f1) wg.go(f2) or wg = WorkGroup(ctx) wg.go(f1) wg.go(f2) wg.wait() This is sometimes handy and is referred to as "structured concurrency" in Python world. sync.Sema, sync.Mutex, sync.RWMutex already support "with". sync.WaitGroup is imho too low-level, but we might consider adding "with" support for it in the future as well. In general pygolang way is to use defer instead of plugging all classes with __enter__/__exit__ "with" support, but for small well-known class of concurrency-related things its seems "with" support is worth it: - having "with" for sync.Mutex+co allows it to be used as a drop-in replacement instead of threading.Lock+co, and - having "with" for sync.WorkGroup - the most commonly-used tool to spawn jobs and wait for their completion - makes it on-par with "structured concurrency". /reviewed-on !12
-
Kirill Smelkov authored
WorkGroup methods work on PyWorkGroup, not on PyWaitGroup. This probably used to work because Cython ignores (?) provided type of self? /reviewed-on !12
-
- 10 Dec, 2020 1 commit
-
-
Kirill Smelkov authored
Similarly to test_pymain_syspath we cannot run this test on SlapOS because with buildout raw underlying python interpreter does not have access to eggs with which gpython script was generated. See 0fa9d6e7 and 92bb5bcc for details. Without this patch running pygolang tests fails on SlapOS as shown below: (pygolang-env) slapuser34@vifibcloud-rapidspace-hosting-007:~/srv/runner/software/44fe7dd3f13ecd100894c6368a35c055/parts/pygolang-dev$ gpython -m pytest -vsx -k relpath ================================================= test session starts ================================================== platform linux2 -- Python 2.7.18, pytest-4.6.11, py-1.9.0, pluggy-0.13.1 -- /srv/slapgrid/slappart34/srv/runner/software/44fe7dd3f13ecd100894c6368a35c055/bin/gpython cachedir: .pytest_cache rootdir: /srv/slapgrid/slappart34/srv/runner/software/44fe7dd3f13ecd100894c6368a35c055/parts/pygolang-dev collected 115 items / 114 deselected / 1 selected gpython/gpython_test.py::test_pymain_run_via_relpath Traceback (most recent call last): File "./__init__.py", line 511, in <module> main() File "./__init__.py", line 395, in main pymain(argv, init) File "./__init__.py", line 217, in pymain init() File "./__init__.py", line 364, in init import gevent ImportError: No module named gevent FAILED ======================================================= FAILURES ======================================================= _____________________________________________ test_pymain_run_via_relpath ______________________________________________ @gpython_only def test_pymain_run_via_relpath(): argv = ['-c', 'import sys; print(sys.version)'] out1 = pyout( argv, pyexe=sys.executable) > out2 = pyout(['./__init__.py'] + argv, pyexe=sys._gpy_underlying_executable, cwd=here) gpython/gpython_test.py:301: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ golang/golang_test.py:1842: in pyout return pyrun(argv, stdin=stdin, stdout=stdout, stderr=stderr, **kw) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ argv = ['./__init__.py', '-c', 'import sys; print(sys.version)'], stdin = None, stdout = '', stderr = None kw = {'cwd': '/srv/slapgrid/slappart34/srv/runner/software/44fe7dd3f13ecd100894c6368a35c055/parts/pygolang-dev/gpython', 'pyexe': '/srv/slapgrid/slappart34/srv//runner//shared/python2.7/44578f5389723084b136574c34bc8023/bin/python2.7'} 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: ./__init__.py -c import sys; print(sys.version) E (failed) golang/golang_test.py:1836: RuntimeError ======================================= 1 failed, 114 deselected in 0.73 seconds ======================================= Fixes 076cdd8f (gpython: Fix crash when invoked as e.g. ./bin/gpython). /reviewed-on nexedi/pygolang!11
-
- 06 Dec, 2020 1 commit
-
-
Kirill Smelkov authored
PyPy changed home from bitbucket to foss.heptapod recently[1]. The old links on bitbucket no longer works. -> Update bitbucket links to their correspondents on foss.heptapod.net . [1] https://morepypy.blogspot.com/2020/02/pypy-and-cffi-have-moved-to-heptapod.html
-
- 02 Dec, 2020 2 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
PyPy2 implements -OO differently compared to CPython and it breaks zope.interfaces at import time: https://foss.heptapod.net/pypy/pypy/-/issues/3356.
-
- 01 Dec, 2020 1 commit
-
-
Kirill Smelkov authored
- Teach gpython and pymain about `-`; - Teach gpython and pymain about -O; - Teach pymain to always set sys.executable, so that subprocess and multiprocessing work correctly out of the box; - Fix ./bin/gpython crash; - Rewrite options parsing via incremental getopt-like thing. This changes are motivated by nexedi/slapos!862 (comment 121470) and nexedi/slapos!862 (comment 121600). /reviewed-by @jerome /reviewed-on nexedi/pygolang!10
-
- 27 Nov, 2020 1 commit
-
-
Kirill Smelkov authored
Reported by @jerome here: nexedi/slapos!862 (comment 121738)
-
- 26 Nov, 2020 5 commits
-
-
Kirill Smelkov authored
Let's teach gpython and pymain about -O because buildout calls `python -O` to byte-compile python sources in optimized mode: nexedi/slapos!862 (comment 121470) When seeing -O, we take the approach to reexecute underlying python with -O, so that e.g. gpython -O file.py becomes executed as python -O gpython file.py This ensures correctness. The same approach could be used to implement support for e.g. -S and other low-level options. An earlier attempt to implement -O without reexecution can be seen at nexedi/pygolang!7 together with list of problems that arise via that way. Original idea to reexecute itself come from @jerome.
-
Kirill Smelkov authored
There was an assert because sys.path[0] is setup as realpath (real, not relative), but if exe was given as relative path it was raising like below: gpython/gpython_test.py::test_pymain_run_via_relpath GPython 0.0.7.post1 [gevent 20.9.0] / CPython 3.8.6 Traceback (most recent call last): File "./__init__.py", line 482, in <module> main() File "./__init__.py", line 366, in main pymain(argv, init) File "./__init__.py", line 82, in pymain raise RuntimeError('pymain: internal error: sys.path[0] was not set by underlying python to dirname(exe):' RuntimeError: pymain: internal error: sys.path[0] was not set by underlying python to dirname(exe): exe: ./__init__.py sys.path[0]: /home/kirr/src/tools/go/pygolang-master/gpython FAILED -> Fix it by setting up exe as realpath.
-
Kirill Smelkov authored
This is generic step and should be done under both gpython and standard python. Handling sys.executable inside pymain offloads users from setting up sys.executable by themselves, e.g. as in here: https://lab.nexedi.com/nexedi/slapos/blob/46ed2afe/component/pygolang/buildout.cfg#L39-43
-
Kirill Smelkov authored
In other words pymain now requires to be passed in full argv when called. We will need exe=argv[0] in a followup patch to be able to reexecute underlying python interpreter when given options like -O, -S, etc... This is change in behaviour and in general must come with changing pymain name - e.g. to pymain2 - so that old pymain continues to work as before. However since there are not so many known pymain users, we can probably do this change in place since we'll care ourselves about all those users: - [python-interpreter] in SlapOS: https://lab.nexedi.com/nexedi/slapos/blob/46ed2afe/component/pygolang/buildout.cfg#L30-53 - pyruntraced in Go123: https://lab.nexedi.com/kirr/go123/blob/96046edf/tracing/cmd/pyruntraced - zobjtrace in ZODB: https://lab.nexedi.com/kirr/ZODB/blob/07c21671/zobjtrace So I hope it is ok.
-
Kirill Smelkov authored
Python allows multiple single-letter options and their arguments to be coming on single argument, for example: python -OQc'print 1' python -OQc 'print 1' python -OQ -c 'print 1' etc... We are currently trying to handle that at every option, but even though it kind of works, it is limited and will break once we will start adding options. -> Refactor options parsing into getopt-style helper. We cannot use getopt itself because it will complain e.g. on `gpython file.py --my-custom-opt` that my-custom-opt is unexpected.
-