- 30 Oct, 2018 5 commits
-
-
Kirill Smelkov authored
`defer` allows to schedule a cleanup to be executed when current function returns. It is similar to `try`/`finally` but does not force the cleanup part to be far away in the end. For example:: wc = wcfs.join(zurl) │ wc = wcfs.join(zurl) defer(wc.close) │ try: │ ... ... │ ... ... │ ... ... │ finally: │ wc.close() For completeness there is `recover` and `panic` that allow to program with Go-style error handling, for example:: def _(): r = recover() if r is not None: print("recovered. error was: %s" % (r,)) defer(_) ... panic("aaa") But `recover` and `panic` are probably of less utility since they can be practically natively modelled with `try`/`except`. If `defer` is used, the function that uses it must be wrapped with `@func` or `@method` decorators. The implementation is partly inspired by work of Denis Kolodin: - https://habr.com/post/191786 - https://stackoverflow.com/a/43028386/9456786
-
Kirill Smelkov authored
While the second phase of select is running we queue send/recv cases to corresponding channels. At some point - when some of the cases are already queued - a peer goroutine might try to send/recv on that channel. And it will succeed because a waiter was queued to the channel. At the same time select is continuing its enqueue loop and before enqueuing to a channel it tries to send/recv there. If that channel became just ready (i.e. just after select poll phase) the try to send/recv will succeed. This means that actually 2 select cases could be executed at the same time. Fix it by carefully checking whether some case already won before trying to send/recv on a channel. This fixes the test failures that were demonstrated by previous 2 patches.
-
Kirill Smelkov authored
Previous select-select test uses 2 channels and recreats them every iteration. However the bug we just saw in b51b8d5d (select: Run tests more thoroughly) is of parasitic nature - where misbehaviour depends on what state has been left there from previous select and whether the race to get to that state fast enough succeeded. So add a more secialized test which tries to trigger the parasitic effects that depend on previous state left by select on the channels. The test, similarly to b51b8d5d, currently fails.
-
Kirill Smelkov authored
With more iterations it triggers a bug: kirr@deco:~/src/tools/go/pygolang$ py.test -vsx ============================================== test session starts =============================================== platform linux2 -- Python 2.7.15+, pytest-3.6.4, py-1.6.0, pluggy-0.6.0 -- /usr/bin/python2 cachedir: .pytest_cache rootdir: /home/kirr/src/tools/go/pygolang, inifile: collected 7 items golang/_gopath_test.py::test_import_module PASSED golang/_gopath_test.py::test_import_package PASSED golang/gcompat_test.py::test_qq PASSED golang/golang_test.py::test_go PASSED golang/golang_test.py::test_chan PASSED golang/golang_test.py::test_select Exception in thread Thread-117: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 754, in run self.__target(*self.__args, **self.__kwargs) File "/home/kirr/src/tools/go/pygolang/golang/golang_test.py", line 320, in _ assert (_, _rx) == (1, 'b') AssertionError: assert (1, 'xxx1') == (1, 'b') At index 1 diff: 'xxx1' != 'b' Full diff: - (1, 'xxx1') + (1, 'b')
-
Kirill Smelkov authored
This test was failing when pygolang was not dev-mode installed (`pip install -e .`): kirr@deco:~/src/tools/go/pygolang$ py.test =========================================== test session starts ============================================ platform linux2 -- Python 2.7.15+, pytest-3.6.4, py-1.6.0, pluggy-0.6.0 rootdir: /home/kirr/src/tools/go/pygolang, inifile: collected 8 items golang/_gopath_test.py .. [ 25%] golang/gcompat_test.py . [ 37%] golang/golang_test.py F.... [100%] ================================================= FAILURES ================================================= _________________________________________________ test_go __________________________________________________ def test_go(): # leaked goroutine behaviour check: done in separate process because we need # to test process termination exit there. subprocess.check_call([sys.executable, > dirname(__file__) + "/golang_test_goleaked.py"]) golang/golang_test.py:38: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ popenargs = (['/usr/bin/python2', '/home/kirr/src/tools/go/pygolang/golang/golang_test_goleaked.py'],) kwargs = {}, retcode = 1 cmd = ['/usr/bin/python2', '/home/kirr/src/tools/go/pygolang/golang/golang_test_goleaked.py'] def check_call(*popenargs, **kwargs): """Run command with arguments. Wait for command to complete. If the exit code was zero then return, otherwise raise CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute. The arguments are the same as for the Popen constructor. Example: check_call(["ls", "-l"]) """ retcode = call(*popenargs, **kwargs) if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] > raise CalledProcessError(retcode, cmd) E CalledProcessError: Command '['/usr/bin/python2', '/home/kirr/src/tools/go/pygolang/golang/golang_test_goleaked.py']' returned non-zero exit status 1 /usr/lib/python2.7/subprocess.py:190: CalledProcessError ------------------------------------------- Captured stderr call ------------------------------------------- Traceback (most recent call last): File "/home/kirr/src/tools/go/pygolang/golang/golang_test_goleaked.py", line 23, in <module> from golang import go, chan ImportError: No module named golang ==================================== 1 failed, 7 passed in 0.10 seconds ==================================== Fix it by injecting top-level pygolang/ into $PYTHONPATH when testing via external processes. Fixes 69cef96e (go: Don't allow leaked goroutines to prevent program to exit)
-
- 25 Oct, 2018 1 commit
-
-
Kirill Smelkov authored
There was no test for @method so far and that's why it went unnoticed. But on Python3 it breaks on f.func_name: In [3]: def f(): pass In [4]: f.func_name --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-4-662dcbac1531> in <module>() ----> 1 f.func_name AttributeError: 'function' object has no attribute 'func_name' Fix it by using f.__name__ which works on both py2 and py3. Add test for @method to make sure it doesn't break unnoticed.
-
- 24 Oct, 2018 1 commit
-
-
Kirill Smelkov authored
This is the Go behaviour, as demonstratd by the following program: ---- 8< ---- package main import ( "fmt" "time" ) func work(w int) { for i := 0; ; i++ { fmt.Printf("w%d: %d\n", w, i) time.Sleep(1*time.Second) } } func main() { for i := 0; i < 100; i++ { go work(i) } time.Sleep(3*time.Second) println("main: exit") } ---- 8< ----
-
- 04 Jul, 2018 2 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
+ corresponding bits in golang.testing package. py.bench description follows: """ py.bench, similarly to py.test, discovers bench_* functions and Bench* classes and then runs each discovered benchmark via golang.testing.benchmark. Similarly to `go test -bench`, benchmarking results are printed in Go benchmark format. For example, running py.bench on the following code:: def bench_add(b): x, y = 1, 2 for i in xrange(b.N): x + y gives something like:: $ py.bench --count=3 x.py ... pymod: bench_add.py Benchmarkadd 50000000 0.020 µs/op Benchmarkadd 50000000 0.020 µs/op Benchmarkadd 50000000 0.020 µs/op """ The implementation is based on t/py.bench from Wendelin.core - see following commits for its history: lab.nexedi.com/nexedi/wendelin.core/commit/51f252d4 lab.nexedi.com/nexedi/wendelin.core/commit/074ce24d lab.nexedi.com/nexedi/wendelin.core/commit/ed13c3f9 lab.nexedi.com/nexedi/wendelin.core/commit/fc08766d lab.nexedi.com/nexedi/wendelin.core/commit/5a1ed45a lab.nexedi.com/nexedi/wendelin.core/commit/bcab1246
-
- 02 Jul, 2018 4 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
-
Kirill Smelkov authored
Python3 complains that there is no .im_func & friends of a method. Workaround it all with compat code.
-
Kirill Smelkov authored
This patch made its first step as a way to teach qq to also work on python3. However the differences in str / unicode and escapes in between py2 / py3 quickly popped out and then it became easier to just handle whole escaping logic myself. The implementation is based on kirr/go123@c0bbd06e and byproduct of manual handling is that now we don't escape printable UTF-8 characters.
-
- 20 Jun, 2018 2 commits
-
-
Kirill Smelkov authored
Go benchmark format is described here: https://github.com/golang/proposal/blob/master/design/14313-benchmark-format.md Additionally we support extension to that format: - a line starting with `*** neotest:` denotes start of neotest extension block. The block consists of labels describing e.g. hardware and software on a node. The block ends with a blank line. Labels in the block are not added to benchmarking lines from main stream. The block itself should not contain benchmark lines. and upon processing benchmark units are normalized to common base, similarly to golang.org/cl/82955 golang.org/cl/82956 golang.org/cl/82957 Orignally implemented here: kirr/neo@502d9477 kirr/neo@a9b10a45 kirr/neo@f5fec740 kirr/neo@916782b6
-
Kirill Smelkov authored
Not only we can import modules by full path, but now we can also spawn threads/coroutines and exchange data in between them with the same primitives and semantic as in Go. The bulk of new functionality is copied from here: go123@9e1aa6ab Original commit description follows: """ golang: New _Python_ package to provide Go-like features to Python language - `go` spawns lightweight thread. - `chan` and `select` provide channels with Go semantic. - `method` allows to define methods separate from class. - `gimport` allows to import python modules by full path in a Go workspace. The focus of first draft was on usage interface and on correctness, not speed. In particular select should be fully working. If there is a chance I will maybe try to followup with gevent-based implementation in the future. Hide whitespace changes """
-
- 21 May, 2018 2 commits
-
-
Kirill Smelkov authored
Module gopath provides way to import python modules by full path in a Go workspace. For example lonet = gopath.gimport('lab.nexedi.com/kirr/go123/xnet/lonet') will import either lab.nexedi.com/kirr/go123/xnet/lonet.py, or lab.nexedi.com/kirr/go123/xnet/lonet/__init__.py located somewhere under $GOPATH.
-
Kirill Smelkov authored
A simple project to allow python imports to be done by full path in a Go workspace.
-