Commit ac87a2ed authored by Kirill Smelkov's avatar Kirill Smelkov

X Update on my draft state of x/gpystr work

Please see demo/pickle_py2_gpy3_demo.py and demo/ZODB_py2_gpy3_demo.py
for details of how pickle compatibility problem is solved in between py2 and py3.
parent e035c704
x.pkl
data.fs*
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Program ZODB_py2_gpy3_demo demonstrates interoperability in between py2 and py3
# regarding pickled strings in ZODB.
#
# It is similar to pickle_py2_gpy3_demo, but persists data inside ZODB instead
# of raw pickle file.
#
# Please see pickle_py2_gpy3_demo for details.
from __future__ import print_function
from persistent import Persistent
from ZODB.FileStorage import FileStorage
from ZODB.DB import DB
import transaction
from zodbpickle import fastpickle as pickle
import pickletools
import sys
class MyClass(Persistent):
__slots__ = ('data',)
def main():
print(sys.version)
# adjust FileStorage magic so that py3 does not refuse to load FileStorage produced on py2
fsmod = __import__('ZODB.FileStorage.FileStorage', fromlist=['ZODB'])
assert hasattr(fsmod, 'packed_version')
fsmod.packed_version = b'FS21'
stor = FileStorage('data.fs')
db = DB(stor)
conn = db.open()
root = conn.root
if not hasattr(root, 'obj'):
root.obj = obj = MyClass()
obj.data = u'αβγ'.encode('utf-8')
else:
print('\nloading data:')
obj = root.obj
print('\n-> %r\t(%s)' % (obj.data, obj.data))
obj.data += b' %d' % len(obj.data)
print('\nsaving data: %r\t(%s)' % (obj.data, obj.data))
transaction.commit()
if __name__ == '__main__':
main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Program pickle_py2_gpy3_demo demonstrates interoperability in between py2 and py3
# regarding pickled strings.
#
# It initially saves non-ASCII string in pickled form into a file, and on
# further runs tries to load saved object back, appends some tail data to it,
# and saves the result again.
#
# When run on plain py2 everything works as expected: string is initially
# persisted ok, then loaded ok as the same str object, which can be worked with
# as expected, and persisted again ok.
#
# When plain py3 runs this program on the file prepared by py2, loading pickle
# data breaks because, by default, py3 wants to decode *STRING opcodes as ASCII
# and the saved string is not ASCII.
#
# However when run under gpy3, the string is loaded ok as bstr. Since bstr has the
# same semantic as regular str on py2, working with that object produces the
# same result plain py2 would produce when adjusting the data. And then, bstr
# is also persisted ok and via the same *STRING opcodes, that py2 originally
# used for the data.
#
# This way both py2 and gpy3 can interoperate on the same database: py2 can
# produce data, gpy3 can read the data and modify it, and further py2 can load
# updated data, again, just ok.
from __future__ import print_function
from zodbpickle import fastpickle as pickle
import pickletools
from os.path import exists
import sys
def main():
stor = 'x.pkl'
print(sys.version)
if not exists(stor):
obj = u'αβγ'.encode('utf-8')
else:
pkl = readfile(stor)
print('\nloading pickle:')
pickletools.dis(pkl)
obj = pickle.loads(pkl)
print('\n-> %r\t(%s)' % (obj, obj))
obj += b' %d' % len(obj)
print('\nsaving obj: %r\t(%s)' % (obj, obj))
pkl = pickle.dumps(obj)
pickletools.dis(pkl)
writefile(stor, pkl)
def readfile(path):
with open(path, 'rb') as f:
return f.read()
def writefile(path, data):
with open(path, 'wb') as f:
f.write(data)
if __name__ == '__main__':
main()
...@@ -38,13 +38,13 @@ __version__ = "0.1" ...@@ -38,13 +38,13 @@ __version__ = "0.1"
__all__ = ['go', 'chan', 'select', 'default', 'nilchan', 'defer', 'panic', __all__ = ['go', 'chan', 'select', 'default', 'nilchan', 'defer', 'panic',
'recover', 'func', 'error', 'b', 'u', 'bstr', 'ustr', 'bbyte', 'uchr', 'gimport'] 'recover', 'func', 'error', 'b', 'u', 'bstr', 'ustr', 'bbyte', 'uchr', 'gimport']
import setuptools_dso
setuptools_dso.dylink_prepare_dso('golang.runtime.libgolang')
from golang._gopath import gimport # make gimport available from golang from golang._gopath import gimport # make gimport available from golang
import inspect, sys import inspect, sys
import decorator, six import decorator, six
import setuptools_dso
setuptools_dso.dylink_prepare_dso('golang.runtime.libgolang')
from golang._golang import _pysys_exc_clear as _sys_exc_clear from golang._golang import _pysys_exc_clear as _sys_exc_clear
# @func is a necessary decorator for functions for selected golang features to work. # @func is a necessary decorator for functions for selected golang features to work.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# distutils: language = c++ # distutils: language = c++
# distutils: depends = libgolang.h os/signal.h unicode/utf8.h _golang_str.pyx _golang_str_pickle.pyx # distutils: depends = libgolang.h os/signal.h unicode/utf8.h _golang_str.pyx _golang_str_pickle.pyx
# #
# Copyright (C) 2018-2023 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
......
This diff is collapsed.
// Copyright (C) 2023 Nexedi SA and Contributors. // Copyright (C) 2023-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your // it under the terms of the GNU General Public License version 3, or (at your
...@@ -288,7 +288,7 @@ inside_counted_stk: ...@@ -288,7 +288,7 @@ inside_counted_stk:
// disable executable stack // disable executable stack
#ifndef LIBGOLANG_OS_windows #ifdef LIBGOLANG_OS_linux
.section .note.GNU-stack,"",@progbits .section .note.GNU-stack,"",@progbits
#endif #endif
...@@ -304,7 +304,7 @@ inside_counted_stk: ...@@ -304,7 +304,7 @@ inside_counted_stk:
#if defined(LIBGOLANG_ARCH_386) #if defined(LIBGOLANG_ARCH_386)
#ifdef LIBGOLANG_CC_msc #ifdef LIBGOLANG_OS_windows // both msvc and clang-cl
# define CSYM_FASTCALL3(name) @name@12 // MSVC mangles __fastcall # define CSYM_FASTCALL3(name) @name@12 // MSVC mangles __fastcall
# define CSYM_FASTCALL4(name) @name@16 # define CSYM_FASTCALL4(name) @name@16
#else #else
......
This diff is collapsed.
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2023 Nexedi SA and Contributors. # Copyright (C) 2023-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your # it under the terms of the GNU General Public License version 3, or (at your
...@@ -102,16 +102,16 @@ cdef extern from * nogil: ...@@ -102,16 +102,16 @@ cdef extern from * nogil:
int CALLCONV(fastcall) int CALLCONV(fastcall)
tfunc_fastcall3(int x, int y, int z) { return x; } tfunc_fastcall3(int x, int y, int z) { return x; }
#ifndef LIBGOLANG_CC_msc // see note about C3865 in FOR_EACH_CALLCONV # ifndef LIBGOLANG_CC_msc // see note about C3865 in FOR_EACH_CALLCONV
int CALLCONV(thiscall) int CALLCONV(thiscall)
tfunc_thiscall1(int x) { return x; } tfunc_thiscall1(int x) { return x; }
int CALLCONV(thiscall) int CALLCONV(thiscall)
tfunc_thiscall2(int x, int y) { return x; } tfunc_thiscall2(int x, int y) { return x; }
int CALLCONV(thiscall) int CALLCONV(thiscall)
tfunc_thiscall3(int x, int y, int z) { return x; } tfunc_thiscall3(int x, int y, int z) { return x; }
#endif # endif
#ifndef LIBGOLANG_CC_msc // no regparm on MSCV # ifndef LIBGOLANG_CC_msc // no regparm on MSVC
int CALLCONV(regparm(1)) int CALLCONV(regparm(1))
tfunc_regparm1_1(int x) { return x; } tfunc_regparm1_1(int x) { return x; }
int CALLCONV(regparm(1)) int CALLCONV(regparm(1))
...@@ -132,7 +132,7 @@ cdef extern from * nogil: ...@@ -132,7 +132,7 @@ cdef extern from * nogil:
tfunc_regparm3_2(int x, int y) { return x; } tfunc_regparm3_2(int x, int y) { return x; }
int CALLCONV(regparm(3)) int CALLCONV(regparm(3))
tfunc_regparm3_3(int x, int y, int z) { return x; } tfunc_regparm3_3(int x, int y, int z) { return x; }
#endif # endif
static std::vector<_Test_cfunc_is_callee_clenup> _cfunc_is_callee_cleanup_testv = { static std::vector<_Test_cfunc_is_callee_clenup> _cfunc_is_callee_cleanup_testv = {
CASE(tfunc_cdecl1 , 0 * 4), CASE(tfunc_cdecl1 , 0 * 4),
...@@ -144,12 +144,12 @@ cdef extern from * nogil: ...@@ -144,12 +144,12 @@ cdef extern from * nogil:
CASE(tfunc_fastcall1 , 0 * 4), CASE(tfunc_fastcall1 , 0 * 4),
CASE(tfunc_fastcall2 , 0 * 4), CASE(tfunc_fastcall2 , 0 * 4),
CASE(tfunc_fastcall3 , 1 * 4), CASE(tfunc_fastcall3 , 1 * 4),
#ifndef LIBGOLANG_CC_msc # ifndef LIBGOLANG_CC_msc
CASE(tfunc_thiscall1 , 0 * 4), CASE(tfunc_thiscall1 , 0 * 4),
CASE(tfunc_thiscall2 , 1 * 4), CASE(tfunc_thiscall2 , 1 * 4),
CASE(tfunc_thiscall3 , 2 * 4), CASE(tfunc_thiscall3 , 2 * 4),
#endif # endif
#ifndef LIBGOLANG_CC_msc # ifndef LIBGOLANG_CC_msc
CASE(tfunc_regparm1_1 , 0 * 4), CASE(tfunc_regparm1_1 , 0 * 4),
CASE(tfunc_regparm1_2 , 0 * 4), CASE(tfunc_regparm1_2 , 0 * 4),
CASE(tfunc_regparm1_3 , 0 * 4), CASE(tfunc_regparm1_3 , 0 * 4),
...@@ -159,7 +159,7 @@ cdef extern from * nogil: ...@@ -159,7 +159,7 @@ cdef extern from * nogil:
CASE(tfunc_regparm3_1 , 0 * 4), CASE(tfunc_regparm3_1 , 0 * 4),
CASE(tfunc_regparm3_2 , 0 * 4), CASE(tfunc_regparm3_2 , 0 * 4),
CASE(tfunc_regparm3_3 , 0 * 4), CASE(tfunc_regparm3_3 , 0 * 4),
#endif # endif
}; };
#else #else
......
# Copyright (C) 2018-2019 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -34,11 +34,7 @@ from __future__ import print_function, absolute_import ...@@ -34,11 +34,7 @@ from __future__ import print_function, absolute_import
import os, os.path import os, os.path
import sys import sys
import six
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
import imp
# _gopathv returns $GOPATH vector. # _gopathv returns $GOPATH vector.
def _gopathv(): def _gopathv():
...@@ -51,11 +47,25 @@ def _gopathv(): ...@@ -51,11 +47,25 @@ def _gopathv():
# gimport imports python module or package from fully-qualified module name under $GOPATH. # gimport imports python module or package from fully-qualified module name under $GOPATH.
def gimport(name): def gimport(name):
imp.acquire_lock() _gimport_lock()
try: try:
return _gimport(name) return _gimport(name)
finally: finally:
imp.release_lock() _gimport_unlock()
# on py2 there is global import lock
# on py3 we need to organize our own gimport synchronization
if six.PY2:
import imp
_gimport_lock = imp.acquire_lock
_gimport_unlock = imp.release_lock
else:
from importlib import machinery as imp_machinery
from importlib import util as imp_util
from golang import sync
_gimport_mu = sync.Mutex()
_gimport_lock = _gimport_mu.lock
_gimport_unlock = _gimport_mu.unlock
def _gimport(name): def _gimport(name):
# we will register imported module into sys.modules with adjusted path. # we will register imported module into sys.modules with adjusted path.
...@@ -93,4 +103,16 @@ def _gimport(name): ...@@ -93,4 +103,16 @@ def _gimport(name):
# https://stackoverflow.com/a/67692 # https://stackoverflow.com/a/67692
return imp.load_source(modname, modpath) return _imp_load_source(modname, modpath)
def _imp_load_source(modname, modpath):
if six.PY2:
return imp.load_source(modname, modpath)
# https://docs.python.org/3/whatsnew/3.12.html#imp
loader = imp_machinery.SourceFileLoader(modname, modpath)
spec = imp_util.spec_from_file_location(modname, modpath, loader=loader)
mod = imp_util.module_from_spec(spec)
sys.modules[modname] = mod
loader.exec_module(mod)
return mod
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# cython: language_level=2 # cython: language_level=2
# Copyright (C) 2018-2023 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
......
#ifndef _NXD_LIBGOLANG_FMT_H #ifndef _NXD_LIBGOLANG_FMT_H
#define _NXD_LIBGOLANG_FMT_H #define _NXD_LIBGOLANG_FMT_H
// Copyright (C) 2019-2023 Nexedi SA and Contributors. // Copyright (C) 2019-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
This diff is collapsed.
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2018-2023 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -26,6 +26,7 @@ from golang._golang import _udata, _bdata ...@@ -26,6 +26,7 @@ from golang._golang import _udata, _bdata
from golang.gcompat import qq from golang.gcompat import qq
from golang.strconv_test import byterange from golang.strconv_test import byterange
from golang.golang_test import readfile, assertDoc, _pyrun, dir_testprog, PIPE from golang.golang_test import readfile, assertDoc, _pyrun, dir_testprog, PIPE
from gpython import _tEarlyStrSubclass
from pytest import raises, mark, skip from pytest import raises, mark, skip
import sys import sys
import six import six
...@@ -2558,6 +2559,50 @@ def test_strings_patched_transparently(): ...@@ -2558,6 +2559,50 @@ def test_strings_patched_transparently():
assert _(b'cde') == b'abcde' assert _(b'cde') == b'abcde'
# verify that str subclasses, created before str/unicode are replaced with
# bstr/ustr, continue to work ok.
#
# Even though we try to patch string types early, there are always some str
# subclasses created by builtin modules before golang is loaded. For example
# enum.StrEnum is created early during python startup process via
# pathlib -> fnmatch -> re -> enum import. So if we don't preserve those
# classes to continue to work correctly things are breaking badly.
#
# XXX note !gpystr_only ...
# XXX also test bytes?
def tests_strings_early_str_subclass():
xstr = _tEarlyStrSubclass
# .tp_new should be adjusted to point to current str
# (else str.__new__ breaks with "str.__new__(xstr) is not safe ...")
obj = str.__new__(xstr, 'abc')
assert type(obj) is xstr
assert obj == 'abc'
assert xstr.__new__ is str.__new__
# follow-up .__init__ should be noop (enum uses str.__init__ for real)
obj.__init__('xyz')
assert obj == 'abc'
assert str.__init__ is object.__init__
assert xstr.__init__ is str.__init__
# XXX place
assert xstr.__base__ is str
assert xstr.__bases__ == (str,)
# XXX __bases__ + __mro__ for MI
"""
assert str.__base__ is object
assert str.__bases__ == (object,)
"""
# XXX more...
# ---- benchmarks ---- # ---- benchmarks ----
# utf-8 decoding # utf-8 decoding
......
...@@ -1682,6 +1682,12 @@ def test_defer_excchain_dump_ipython(): ...@@ -1682,6 +1682,12 @@ def test_defer_excchain_dump_ipython():
# ----//---- (pytest) # ----//---- (pytest)
def test_defer_excchain_dump_pytest(): def test_defer_excchain_dump_pytest():
# pytest 7.4 also changed traceback output format
# similarly to ipython we do not need to test it becase we activate
# pytest-related patch only on py2 for which latest pytest version is 4.6.11 .
import pytest
if six.PY3 and pytest.version_tuple >= (7,4):
skip("pytest is patched only on py2; pytest7.4 changed traceback format")
tbok = readfile(dir_testprog + "/golang_test_defer_excchain.txt-pytest") tbok = readfile(dir_testprog + "/golang_test_defer_excchain.txt-pytest")
retcode, stdout, stderr = _pyrun([ retcode, stdout, stderr = _pyrun([
# don't let pytest emit internal deprecation warnings to stderr # don't let pytest emit internal deprecation warnings to stderr
......
#ifndef _NXD_LIBGOLANG_H #ifndef _NXD_LIBGOLANG_H
#define _NXD_LIBGOLANG_H #define _NXD_LIBGOLANG_H
// Copyright (C) 2018-2023 Nexedi SA and Contributors. // Copyright (C) 2018-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
// Copyright (C) 2019-2023 Nexedi SA and Contributors. // Copyright (C) 2019-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
#ifndef _NXD_LIBGOLANG_OS_H #ifndef _NXD_LIBGOLANG_OS_H
#define _NXD_LIBGOLANG_OS_H #define _NXD_LIBGOLANG_OS_H
// //
// Copyright (C) 2019-2023 Nexedi SA and Contributors. // Copyright (C) 2019-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
// Copyright (C) 2021-2023 Nexedi SA and Contributors. // Copyright (C) 2021-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
# Copyright (C) 2019-2023 Nexedi SA and Contributors. # Copyright (C) 2019-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
......
// Copyright (C) 2023 Nexedi SA and Contributors. // Copyright (C) 2023-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your // it under the terms of the GNU General Public License version 3, or (at your
......
#ifndef _NXD_LIBGOLANG_RUNTIME_H #ifndef _NXD_LIBGOLANG_RUNTIME_H
#define _NXD_LIBGOLANG_RUNTIME_H #define _NXD_LIBGOLANG_RUNTIME_H
// Copyright (C) 2023 Nexedi SA and Contributors. // Copyright (C) 2023-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your // it under the terms of the GNU General Public License version 3, or (at your
......
// Copyright (C) 2022-2023 Nexedi SA and Contributors. // Copyright (C) 2022-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
// Copyright (C) 2021-2023 Nexedi SA and Contributors. // Copyright (C) 2021-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
#ifndef _NXD_LIBGOLANG_RUNTIME_INTERNAL_SYSCALL_H #ifndef _NXD_LIBGOLANG_RUNTIME_INTERNAL_SYSCALL_H
#define _NXD_LIBGOLANG_RUNTIME_INTERNAL_SYSCALL_H #define _NXD_LIBGOLANG_RUNTIME_INTERNAL_SYSCALL_H
// Copyright (C) 2021-2023 Nexedi SA and Contributors. // Copyright (C) 2021-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
// Copyright (C) 2018-2023 Nexedi SA and Contributors. // Copyright (C) 2018-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
......
#ifndef _NXD_LIBGOLANG_RUNTIME_PLATFORM_H #ifndef _NXD_LIBGOLANG_RUNTIME_PLATFORM_H
#define _NXD_LIBGOLANG_RUNTIME_PLATFORM_H #define _NXD_LIBGOLANG_RUNTIME_PLATFORM_H
// Copyright (C) 2023 Nexedi SA and Contributors. // Copyright (C) 2023-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your // it under the terms of the GNU General Public License version 3, or (at your
......
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2018-2023 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -247,11 +247,12 @@ def pymain(argv, init=None): ...@@ -247,11 +247,12 @@ def pymain(argv, init=None):
pyimpl = platform.python_implementation() pyimpl = platform.python_implementation()
v = _version_info_str v = _version_info_str
pyver = platform.python_version() # ~ v(sys.version_info) but might also have e.g. '+' at tail
if pyimpl == 'CPython': if pyimpl == 'CPython':
ver.append('CPython %s' % v(sys.version_info)) ver.append('CPython %s' % pyver)
elif pyimpl == 'PyPy': elif pyimpl == 'PyPy':
ver.append('PyPy %s' % v(sys.pypy_version_info)) ver.append('PyPy %s' % v(sys.pypy_version_info))
ver.append('Python %s' % v(sys.version_info)) ver.append('Python %s' % pyver)
else: else:
ver = [] # unknown ver = [] # unknown
...@@ -474,6 +475,7 @@ def main(): ...@@ -474,6 +475,7 @@ def main():
from six.moves import builtins from six.moves import builtins
for k in golang.__all__: for k in golang.__all__:
setattr(builtins, k, getattr(golang, k)) setattr(builtins, k, getattr(golang, k))
# setattr(builtins, 'CCC', CCC) # XXX kill
# sys.version # sys.version
sys.version += (' [GPython %s] [runtime %s] [strings %s]' % (golang.__version__, gpy_runtime_ver, gpy_strings)) sys.version += (' [GPython %s] [runtime %s] [strings %s]' % (golang.__version__, gpy_runtime_ver, gpy_strings))
...@@ -594,8 +596,8 @@ class _IGetOpt: ...@@ -594,8 +596,8 @@ class _IGetOpt:
next = __next__ # for py2 next = __next__ # for py2
# for tests XXX continue by first writing test XXX # for tests: subclass of str that is created before everything else is imported
#1/0 # and before golang patches builtin str/unicode types.
class _tEarlyStrSubclass(str): class _tEarlyStrSubclass(str):
pass pass
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# cython: language_level=2 # cython: language_level=2
# Copyright (C) 2023 Nexedi SA and Contributors. # Copyright (C) 2023-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your # it under the terms of the GNU General Public License version 3, or (at your
......
// Copyright (C) 2023 Nexedi SA and Contributors. // Copyright (C) 2023-2024 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your // it under the terms of the GNU General Public License version 3, or (at your
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2019-2023 Nexedi SA and Contributors. # Copyright (C) 2019-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
......
[build-system] [build-system]
requires = ["setuptools", "wheel", "setuptools_dso >= 2.7", "cython < 3", "gevent"] requires = ["setuptools", "wheel", "setuptools_dso >= 2.8", "cython < 3", "gevent"]
# pygolang | pythonic package setup # pygolang | pythonic package setup
# Copyright (C) 2018-2023 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -189,7 +189,7 @@ class develop(XInstallGPython, _develop): ...@@ -189,7 +189,7 @@ class develop(XInstallGPython, _develop):
# requirements of packages under "golang." namespace # requirements of packages under "golang." namespace
R = { R = {
'cmd.pybench': {'pytest', 'py'}, 'cmd.pybench': {'pytest', 'py'},
'pyx.build': {'setuptools', 'wheel', 'cython < 3', 'setuptools_dso >= 2.7'}, 'pyx.build': {'setuptools', 'wheel', 'cython < 3', 'setuptools_dso >= 2.8'},
'x.perf.benchlib': {'numpy'}, 'x.perf.benchlib': {'numpy'},
} }
# TODO generate `a.b -> a`, e.g. x.perf = join(x.perf.*); x = join(x.*) # TODO generate `a.b -> a`, e.g. x.perf = join(x.perf.*); x = join(x.*)
...@@ -575,7 +575,7 @@ setup( ...@@ -575,7 +575,7 @@ setup(
install_requires = ['gevent', 'six', 'decorator', 'Importing;python_version<="2.7"', install_requires = ['gevent', 'six', 'decorator', 'Importing;python_version<="2.7"',
# only runtime part: for dylink_prepare_dso # only runtime part: for dylink_prepare_dso
'setuptools_dso >= 2.7', 'setuptools_dso >= 2.8',
# pyx.build -> setuptools_dso uses multiprocessing # pyx.build -> setuptools_dso uses multiprocessing
# setuptools_dso uses multiprocessing only on Python3, and only on systems where # setuptools_dso uses multiprocessing only on Python3, and only on systems where
# mp.get_start_method()!='fork', while geventmp does not work on windows. # mp.get_start_method()!='fork', while geventmp does not work on windows.
...@@ -611,6 +611,7 @@ setup( ...@@ -611,6 +611,7 @@ setup(
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy Programming Language :: Python :: Implementation :: PyPy
Operating System :: POSIX Operating System :: POSIX
......
[tox] [tox]
envlist = envlist =
{py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,pypy,pypy3}-{thread,gevent} {py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,py312,pypy,pypy3}-{thread,gevent}
# ThreadSanitizer # ThreadSanitizer
...@@ -10,18 +10,18 @@ envlist = ...@@ -10,18 +10,18 @@ envlist =
# (*) PyPy locks its GIL (see RPyGilAcquire) by manually doing atomic cmpxchg # (*) PyPy locks its GIL (see RPyGilAcquire) by manually doing atomic cmpxchg
# and other games, which TSAN cannot see if PyPy itself was not compiled with # and other games, which TSAN cannot see if PyPy itself was not compiled with
# -fsanitize=thread. # -fsanitize=thread.
{py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311 }-{thread }-tsan {py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,py312 }-{thread }-tsan
# XXX py*-gevent-tsan would be nice to have, but at present TSAN is not # XXX py*-gevent-tsan would be nice to have, but at present TSAN is not
# effective with gevent, because it does not understand greenlet "thread" # effective with gevent, because it does not understand greenlet "thread"
# switching and so perceives the program as having only one thread where races # switching and so perceives the program as having only one thread where races
# are impossible. Disabled to save time. # are impossible. Disabled to save time.
# {py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311 }-{ gevent}-tsan # {py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,py312 }-{ gevent}-tsan
# AddressSanitizer # AddressSanitizer
# XXX asan does not work with gevent: https://github.com/python-greenlet/greenlet/issues/113 # XXX asan does not work with gevent: https://github.com/python-greenlet/greenlet/issues/113
{py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,pypy,pypy3}-{thread }-asan {py27d,py27,py37,py38,py39d,py39,py310d,py310,py311d,py311,py312,pypy,pypy3}-{thread }-asan
[testenv] [testenv]
basepython = basepython =
...@@ -35,6 +35,8 @@ basepython = ...@@ -35,6 +35,8 @@ basepython =
py310: python3.10 py310: python3.10
py311d: python3.11-dbg py311d: python3.11-dbg
py311: python3.11 py311: python3.11
py312: python3.12
py312d: python3.12-dbg
pypy: pypy pypy: pypy
pypy3: pypy3 pypy3: pypy3
...@@ -72,5 +74,5 @@ commands= ...@@ -72,5 +74,5 @@ commands=
# asan/tsan: tell pytest not to capture output - else it is not possible to see # asan/tsan: tell pytest not to capture output - else it is not possible to see
# reports from sanitizers because they crash tested process on error. # reports from sanitizers because they crash tested process on error.
# likewise for python debug builds. # likewise for python debug builds.
asan,tsan,py{27,39,310,311}d: -s \ asan,tsan,py{27,39,310,311,312}d: -s \
gpython/ golang/ gpython/ golang/
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (C) 2019-2020 Nexedi SA and Contributors. # Copyright (C) 2019-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -34,12 +34,13 @@ trun cares to run python with LD_PRELOAD set appropriately to /path/to/libtsan.s ...@@ -34,12 +34,13 @@ trun cares to run python with LD_PRELOAD set appropriately to /path/to/libtsan.s
from __future__ import print_function, absolute_import from __future__ import print_function, absolute_import
import os, sys, re, subprocess, pkgutil import os, sys, re, subprocess, types
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
import imp
PY3 = (bytes is not str) PY3 = (bytes is not str)
if PY3:
from importlib import machinery as imp_machinery
else:
import imp, pkgutil
# env_prepend prepends value to ${name} environment variable. # env_prepend prepends value to ${name} environment variable.
# #
...@@ -64,12 +65,15 @@ def grep1(pattern, text): # -> re.Match|None ...@@ -64,12 +65,15 @@ def grep1(pattern, text): # -> re.Match|None
# to import e.g. golang.pyx.build, or locate golang._golang, without built/working golang. # to import e.g. golang.pyx.build, or locate golang._golang, without built/working golang.
def ximport_empty_golangmod(): def ximport_empty_golangmod():
assert 'golang' not in sys.modules assert 'golang' not in sys.modules
golang = imp.new_module('golang') golang = types.ModuleType('golang')
golang.__package__ = 'golang' golang.__package__ = 'golang'
golang.__path__ = ['golang'] golang.__path__ = ['golang']
golang.__file__ = 'golang/__init__.py' golang.__file__ = 'golang/__init__.py'
golang.__loader__ = pkgutil.ImpLoader('golang', None, 'golang/__init__.py', if PY3:
[None, None, imp.PY_SOURCE]) golang.__loader__ = imp_machinery.SourceFileLoader('golang', 'golang/__init__.py')
else:
golang.__loader__ = pkgutil.ImpLoader('golang', None, 'golang/__init__.py',
[None, None, imp.PY_SOURCE])
sys.modules['golang'] = golang sys.modules['golang'] = golang
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment