pyobject 1.2.6__tar.gz → 1.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyobject-1.2.7/LICENSE +21 -0
- {pyobject-1.2.6/pyobject.egg-info → pyobject-1.2.7}/PKG-INFO +23 -12
- {pyobject-1.2.6 → pyobject-1.2.7}/README.rst +22 -10
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/__init__.py +6 -3
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/browser.py +41 -28
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/pyobj_extension.c +68 -1
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/browser_chs_locale.py +44 -30
- {pyobject-1.2.6 → pyobject-1.2.7/pyobject.egg-info}/PKG-INFO +23 -12
- {pyobject-1.2.6 → pyobject-1.2.7}/setup.py +0 -1
- pyobject-1.2.6/LICENSE +0 -674
- {pyobject-1.2.6 → pyobject-1.2.7}/MANIFEST.in +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/code_.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/back.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/codeobject.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/dict.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/empty_dict.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/empty_list.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/empty_tuple.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/forward.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/function.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/list.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/number.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/python.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/python.ico +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/refresh.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/string.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/images/tuple.gif +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/newtypes.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/search.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/super_reflect.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/README.md +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/__init__.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/empty.pyc +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/interpreter_shutdown.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/pyc_zipper_lzma.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/pyc_zipper_unpack.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/pyc_zipper_zlib.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject/test/testcode.py +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject.egg-info/SOURCES.txt +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject.egg-info/dependency_links.txt +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/pyobject.egg-info/top_level.txt +0 -0
- {pyobject-1.2.6 → pyobject-1.2.7}/setup.cfg +0 -0
pyobject-1.2.7/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 qfcy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyobject
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.7
|
|
4
4
|
Summary: 一个提供操作Python对象底层工具的模块。A utility tool with some submodules for operating internal python objects.
|
|
5
5
|
Home-page: https://github.com/qfcy/pyobject
|
|
6
6
|
Author: qfcy
|
|
7
7
|
Author-email: 3076711200@qq.com
|
|
8
8
|
Keywords: pyobject,python,object,utility,object browser,bytecode,reflect,object search,OOP,对象,字节码,对象浏览器
|
|
9
9
|
Classifier: Programming Language :: Python
|
|
10
|
-
Classifier: Natural Language :: Chinese (Simplified)
|
|
11
10
|
Classifier: Topic :: Utilities
|
|
12
11
|
Classifier: Topic :: Software Development :: Bug Tracking
|
|
13
12
|
Classifier: Topic :: Software Development :: Debuggers
|
|
@@ -143,7 +142,9 @@ def __init__(self, code=None)
|
|
|
143
142
|
|
|
144
143
|
方法
|
|
145
144
|
-------
|
|
146
|
-
|
|
145
|
+
|
|
146
|
+
**主要方法**
|
|
147
|
+
|
|
147
148
|
- ``exec(globals_=None, locals_=None)``:在全局和局部作用域字典中执行代码对象。
|
|
148
149
|
- ``eval(globals_=None, locals_=None)``:在全局和局部作用域字典中执行代码对象,并获取返回值。
|
|
149
150
|
- ``copy()``:复制一份``Code``对象,返回复制的副本。
|
|
@@ -152,20 +153,21 @@ def __init__(self, code=None)
|
|
|
152
153
|
- ``get_flags()``:返回 ``co_flags`` 属性的标志名称列表,如``["NOFREE"]``。
|
|
153
154
|
- ``get_sub_code(name)``:搜索代码的``co_consts``中的子代码,如函数、类定义等,不会递归搜索。返回搜索到的``Code``对象,未找到时抛出``ValueError``。
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
**序列化**
|
|
157
|
+
|
|
156
158
|
- ``to_pycfile(filename)``:使用 ``marshal`` 模块将代码对象转储到 ``.pyc`` 文件中。
|
|
157
159
|
- ``from_pycfile(filename)``:从 ``.pyc`` 文件创建 ``Code`` 实例。
|
|
158
160
|
- ``from_file(filename)``:从 ``.py`` 或 ``.pyc`` 文件创建 ``Code`` 实例。
|
|
159
161
|
- ``pickle(filename)``:将 ``Code`` 对象序列化为 pickle 文件。
|
|
160
162
|
|
|
161
|
-
|
|
163
|
+
**调试和检查**
|
|
162
164
|
|
|
163
165
|
- ``show(*args, **kw)``:在内部调用``pyobject.desc``,显示代码对象的属性,参数用法和``desc()``的用法相同。
|
|
164
166
|
- ``info()``:在内部调用``dis.show_code``,显示字节码的基本信息。
|
|
165
167
|
- ``dis(*args, **kw)``:调用 ``dis`` 模块输出字节码的反汇编,和``dis.dis(c.to_code())``相同。
|
|
166
168
|
- ``decompile(version=None, *args, **kw)``:调用 ``uncompyle6`` 库将代码对象反编译为源代码。(安装``pyobject``库时, ``uncompyle6`` 库是可选的。)
|
|
167
169
|
|
|
168
|
-
|
|
170
|
+
**工厂函数**
|
|
169
171
|
|
|
170
172
|
- ``fromfunc(function)``:从 Python 函数对象创建 ``Code`` 实例,和``Code(func.__code__)``相同。
|
|
171
173
|
- ``fromstring(string, mode='exec', filename='')``:从源代码字符串创建 ``Code`` 实例,参数用法和``compile``内置函数相同,在内部调用``compile()``。
|
|
@@ -244,10 +246,12 @@ list_in(obj, lst)::
|
|
|
244
246
|
本函数直接比较对象的指针,提高了效率。
|
|
245
247
|
|
|
246
248
|
|
|
247
|
-
版本: 1.2.
|
|
249
|
+
版本: 1.2.7
|
|
248
250
|
|
|
249
251
|
更新日志:
|
|
250
252
|
|
|
253
|
+
2025-3-6(v1.2.7):为pyobject.browser新增了``dir()``中不存在的类属性(如``__flags__``, ``__mro__``),修改了pyobj_extension模块。
|
|
254
|
+
|
|
251
255
|
2025-2-15(v1.2.6):修复了pyobject.browser浏览过大对象的卡顿问题,改进了pyobject.code_模块,新增了正在开发中的反射库pyobject.super_reflect,
|
|
252
256
|
在pyobj_extension新增了``getrefcount_nogil``和``setrefcount_nogil``。
|
|
253
257
|
|
|
@@ -388,7 +392,9 @@ Attributes introduced in Python 3.8 and later:
|
|
|
388
392
|
|
|
389
393
|
Methods
|
|
390
394
|
-------
|
|
391
|
-
|
|
395
|
+
|
|
396
|
+
**Core Methods**
|
|
397
|
+
|
|
392
398
|
- ``exec(globals_=None, locals_=None)``: Executes the code object within the provided global and local scope dictionaries.
|
|
393
399
|
- ``eval(globals_=None, locals_=None)``: Executes the code object within the provided global and local scope dictionaries and returns the result.
|
|
394
400
|
- ``copy()``: Creates a copy of the `Code` object and returns the duplicate.
|
|
@@ -397,19 +403,22 @@ Methods
|
|
|
397
403
|
- ``get_flags()``: Returns a list of flag names for the ``co_flags`` attribute, e.g., ``["NOFREE"]``.
|
|
398
404
|
- ``get_sub_code(name)``: Searches for sub-code objects (e.g., functions or class definitions) in the ``co_consts`` attribute. This method does not perform recursive searches. Returns the found `Code` object or raises a ``ValueError`` if not found.
|
|
399
405
|
|
|
400
|
-
|
|
406
|
+
**Serialization**
|
|
407
|
+
|
|
401
408
|
- ``to_pycfile(filename)``: Dumps the code object into a `.pyc` file using the ``marshal`` module.
|
|
402
409
|
- ``from_pycfile(filename)``: Creates a `Code` instance from a `.pyc` file.
|
|
403
410
|
- ``from_file(filename)``: Creates a `Code` instance from a `.py` or `.pyc` file.
|
|
404
411
|
- ``pickle(filename)``: Serializes the `Code` object into a pickle file.
|
|
405
412
|
|
|
406
|
-
|
|
413
|
+
**Debugging and Inspection**
|
|
414
|
+
|
|
407
415
|
- ``show(*args, **kw)``: Internally calls ``pyobject.desc`` to display the attributes of the code object. The parameters are the same as those used in ``desc()``.
|
|
408
416
|
- ``info()``: Internally calls ``dis.show_code`` to display basic information about the bytecode.
|
|
409
417
|
- ``dis(*args, **kw)``: Calls the ``dis`` module to output the disassembly of the bytecode, equivalent to ``dis.dis(c.to_code())``.
|
|
410
418
|
- ``decompile(version=None, *args, **kw)``: Calls the ``uncompyle6`` library to decompile the code object into source code. (The ``uncompyle6`` library is optional when installing the ``pyobject`` package.)
|
|
411
419
|
|
|
412
|
-
|
|
420
|
+
**Factory Functions**
|
|
421
|
+
|
|
413
422
|
- ``fromfunc(function)``: Creates a `Code` instance from a Python function object, equivalent to ``Code(func.__code__)``.
|
|
414
423
|
- ``fromstring(string, mode='exec', filename='')``: Creates a `Code` instance from a source code string. The parameters are the same as those used in the built-in ``compile`` function, which is called internally.
|
|
415
424
|
|
|
@@ -486,11 +495,13 @@ list_in(obj, lst)::
|
|
|
486
495
|
Compared to the built-in Python call "obj in lst" that invokes the "==" operator (__eq__) multiple times, this function directly compares the pointers to improve efficiency.
|
|
487
496
|
|
|
488
497
|
|
|
489
|
-
Version: 1.2.
|
|
498
|
+
Version: 1.2.7
|
|
490
499
|
|
|
491
500
|
Change Log
|
|
492
501
|
==========
|
|
493
502
|
|
|
503
|
+
2025-3-6(v1.2.7): Added support for special class attributes excluded from ``dir()`` (such as ``__flags__``, ``__mro__``) in pyobject.browser and modified the pyobj_extension module.
|
|
504
|
+
|
|
494
505
|
2025-2-15 (v1.2.6): Fixed the lag issue when browsing large objects in ``pyobject.browser``, improved the ``pyobject.code_`` module, introduced a new reflection library
|
|
495
506
|
``pyobject.super_reflect`` currently in development, and added ``getrefcount_nogil`` and ``setrefcount_nogil`` to the ``pyobj_extension`` module.
|
|
496
507
|
|
|
@@ -126,7 +126,9 @@ def __init__(self, code=None)
|
|
|
126
126
|
|
|
127
127
|
方法
|
|
128
128
|
-------
|
|
129
|
-
|
|
129
|
+
|
|
130
|
+
**主要方法**
|
|
131
|
+
|
|
130
132
|
- ``exec(globals_=None, locals_=None)``:在全局和局部作用域字典中执行代码对象。
|
|
131
133
|
- ``eval(globals_=None, locals_=None)``:在全局和局部作用域字典中执行代码对象,并获取返回值。
|
|
132
134
|
- ``copy()``:复制一份``Code``对象,返回复制的副本。
|
|
@@ -135,20 +137,21 @@ def __init__(self, code=None)
|
|
|
135
137
|
- ``get_flags()``:返回 ``co_flags`` 属性的标志名称列表,如``["NOFREE"]``。
|
|
136
138
|
- ``get_sub_code(name)``:搜索代码的``co_consts``中的子代码,如函数、类定义等,不会递归搜索。返回搜索到的``Code``对象,未找到时抛出``ValueError``。
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
**序列化**
|
|
141
|
+
|
|
139
142
|
- ``to_pycfile(filename)``:使用 ``marshal`` 模块将代码对象转储到 ``.pyc`` 文件中。
|
|
140
143
|
- ``from_pycfile(filename)``:从 ``.pyc`` 文件创建 ``Code`` 实例。
|
|
141
144
|
- ``from_file(filename)``:从 ``.py`` 或 ``.pyc`` 文件创建 ``Code`` 实例。
|
|
142
145
|
- ``pickle(filename)``:将 ``Code`` 对象序列化为 pickle 文件。
|
|
143
146
|
|
|
144
|
-
|
|
147
|
+
**调试和检查**
|
|
145
148
|
|
|
146
149
|
- ``show(*args, **kw)``:在内部调用``pyobject.desc``,显示代码对象的属性,参数用法和``desc()``的用法相同。
|
|
147
150
|
- ``info()``:在内部调用``dis.show_code``,显示字节码的基本信息。
|
|
148
151
|
- ``dis(*args, **kw)``:调用 ``dis`` 模块输出字节码的反汇编,和``dis.dis(c.to_code())``相同。
|
|
149
152
|
- ``decompile(version=None, *args, **kw)``:调用 ``uncompyle6`` 库将代码对象反编译为源代码。(安装``pyobject``库时, ``uncompyle6`` 库是可选的。)
|
|
150
153
|
|
|
151
|
-
|
|
154
|
+
**工厂函数**
|
|
152
155
|
|
|
153
156
|
- ``fromfunc(function)``:从 Python 函数对象创建 ``Code`` 实例,和``Code(func.__code__)``相同。
|
|
154
157
|
- ``fromstring(string, mode='exec', filename='')``:从源代码字符串创建 ``Code`` 实例,参数用法和``compile``内置函数相同,在内部调用``compile()``。
|
|
@@ -227,10 +230,12 @@ list_in(obj, lst)::
|
|
|
227
230
|
本函数直接比较对象的指针,提高了效率。
|
|
228
231
|
|
|
229
232
|
|
|
230
|
-
版本: 1.2.
|
|
233
|
+
版本: 1.2.7
|
|
231
234
|
|
|
232
235
|
更新日志:
|
|
233
236
|
|
|
237
|
+
2025-3-6(v1.2.7):为pyobject.browser新增了``dir()``中不存在的类属性(如``__flags__``, ``__mro__``),修改了pyobj_extension模块。
|
|
238
|
+
|
|
234
239
|
2025-2-15(v1.2.6):修复了pyobject.browser浏览过大对象的卡顿问题,改进了pyobject.code_模块,新增了正在开发中的反射库pyobject.super_reflect,
|
|
235
240
|
在pyobj_extension新增了``getrefcount_nogil``和``setrefcount_nogil``。
|
|
236
241
|
|
|
@@ -371,7 +376,9 @@ Attributes introduced in Python 3.8 and later:
|
|
|
371
376
|
|
|
372
377
|
Methods
|
|
373
378
|
-------
|
|
374
|
-
|
|
379
|
+
|
|
380
|
+
**Core Methods**
|
|
381
|
+
|
|
375
382
|
- ``exec(globals_=None, locals_=None)``: Executes the code object within the provided global and local scope dictionaries.
|
|
376
383
|
- ``eval(globals_=None, locals_=None)``: Executes the code object within the provided global and local scope dictionaries and returns the result.
|
|
377
384
|
- ``copy()``: Creates a copy of the `Code` object and returns the duplicate.
|
|
@@ -380,19 +387,22 @@ Methods
|
|
|
380
387
|
- ``get_flags()``: Returns a list of flag names for the ``co_flags`` attribute, e.g., ``["NOFREE"]``.
|
|
381
388
|
- ``get_sub_code(name)``: Searches for sub-code objects (e.g., functions or class definitions) in the ``co_consts`` attribute. This method does not perform recursive searches. Returns the found `Code` object or raises a ``ValueError`` if not found.
|
|
382
389
|
|
|
383
|
-
|
|
390
|
+
**Serialization**
|
|
391
|
+
|
|
384
392
|
- ``to_pycfile(filename)``: Dumps the code object into a `.pyc` file using the ``marshal`` module.
|
|
385
393
|
- ``from_pycfile(filename)``: Creates a `Code` instance from a `.pyc` file.
|
|
386
394
|
- ``from_file(filename)``: Creates a `Code` instance from a `.py` or `.pyc` file.
|
|
387
395
|
- ``pickle(filename)``: Serializes the `Code` object into a pickle file.
|
|
388
396
|
|
|
389
|
-
|
|
397
|
+
**Debugging and Inspection**
|
|
398
|
+
|
|
390
399
|
- ``show(*args, **kw)``: Internally calls ``pyobject.desc`` to display the attributes of the code object. The parameters are the same as those used in ``desc()``.
|
|
391
400
|
- ``info()``: Internally calls ``dis.show_code`` to display basic information about the bytecode.
|
|
392
401
|
- ``dis(*args, **kw)``: Calls the ``dis`` module to output the disassembly of the bytecode, equivalent to ``dis.dis(c.to_code())``.
|
|
393
402
|
- ``decompile(version=None, *args, **kw)``: Calls the ``uncompyle6`` library to decompile the code object into source code. (The ``uncompyle6`` library is optional when installing the ``pyobject`` package.)
|
|
394
403
|
|
|
395
|
-
|
|
404
|
+
**Factory Functions**
|
|
405
|
+
|
|
396
406
|
- ``fromfunc(function)``: Creates a `Code` instance from a Python function object, equivalent to ``Code(func.__code__)``.
|
|
397
407
|
- ``fromstring(string, mode='exec', filename='')``: Creates a `Code` instance from a source code string. The parameters are the same as those used in the built-in ``compile`` function, which is called internally.
|
|
398
408
|
|
|
@@ -469,11 +479,13 @@ list_in(obj, lst)::
|
|
|
469
479
|
Compared to the built-in Python call "obj in lst" that invokes the "==" operator (__eq__) multiple times, this function directly compares the pointers to improve efficiency.
|
|
470
480
|
|
|
471
481
|
|
|
472
|
-
Version: 1.2.
|
|
482
|
+
Version: 1.2.7
|
|
473
483
|
|
|
474
484
|
Change Log
|
|
475
485
|
==========
|
|
476
486
|
|
|
487
|
+
2025-3-6(v1.2.7): Added support for special class attributes excluded from ``dir()`` (such as ``__flags__``, ``__mro__``) in pyobject.browser and modified the pyobj_extension module.
|
|
488
|
+
|
|
477
489
|
2025-2-15 (v1.2.6): Fixed the lag issue when browsing large objects in ``pyobject.browser``, improved the ``pyobject.code_`` module, introduced a new reflection library
|
|
478
490
|
``pyobject.super_reflect`` currently in development, and added ``getrefcount_nogil`` and ``setrefcount_nogil`` to the ``pyobj_extension`` module.
|
|
479
491
|
|
|
@@ -6,7 +6,7 @@ from warnings import warn
|
|
|
6
6
|
from pprint import pprint
|
|
7
7
|
|
|
8
8
|
__author__="qfcy"
|
|
9
|
-
__version__="1.2.
|
|
9
|
+
__version__="1.2.7"
|
|
10
10
|
|
|
11
11
|
_ignore_names=["__builtins__","__doc__"]
|
|
12
12
|
__all__=["objectname","bases","describe","desc"]
|
|
@@ -15,7 +15,8 @@ def objectname(obj):
|
|
|
15
15
|
"""objectname(obj) - Returns the name of an object in the format xxmodule.xxclass.
|
|
16
16
|
For example: objectname(int) -> 'builtins.int'."""
|
|
17
17
|
if not obj.__class__==type:obj=obj.__class__
|
|
18
|
-
if obj.__module__=="__main__":
|
|
18
|
+
if not hasattr(obj,"__module__") or obj.__module__=="__main__":
|
|
19
|
+
return obj.__name__
|
|
19
20
|
return "{}.{}".format(obj.__module__,obj.__name__)
|
|
20
21
|
|
|
21
22
|
###无递归版本
|
|
@@ -106,7 +107,9 @@ except (ImportError,SystemError):warn("Failed to import pyobject.code_.")
|
|
|
106
107
|
try:
|
|
107
108
|
from pyobj_extension import *
|
|
108
109
|
__all__.extend(["convptr","py_incref","py_decref","getrealrefcount",
|
|
109
|
-
"setrefcount","list_in","getrefcount_nogil","setrefcount_nogil"
|
|
110
|
+
"setrefcount","list_in","getrefcount_nogil","setrefcount_nogil",
|
|
111
|
+
"get_type_flag","set_type_flag","set_type_base","set_type_bases",
|
|
112
|
+
"set_type_mro"])
|
|
110
113
|
except ImportError:warn("Failed to import module pyobj_extension.")
|
|
111
114
|
|
|
112
115
|
def test():
|
|
@@ -20,19 +20,18 @@ except ImportError:from __init__ import objectname,_shortrepr
|
|
|
20
20
|
_IMAGE_PATH=os.path.join(os.path.split(__file__)[0],"images")
|
|
21
21
|
SKIP=(WrapperDescriptorType, MethodWrapperType,\
|
|
22
22
|
MethodDescriptorType, ClassMethodDescriptorType)
|
|
23
|
+
TYPE_EXTRA_ATTRS = ("__basicsize__","__dictoffset__","__flags__",
|
|
24
|
+
"__itemsize__","__weakrefoffset__")
|
|
25
|
+
TYPE_EXTRA_CLASS_ATTRS = ("__base__","__bases__","__mro__")
|
|
23
26
|
|
|
24
27
|
def isfunc(obj):
|
|
25
28
|
# 判断一个对象是否为函数或方法
|
|
26
29
|
if isfunction(obj) or ismethod(obj):return True
|
|
27
30
|
# 使用typing而不用types.WrapperDescriptorType是为了与旧版本兼容
|
|
28
31
|
func_types=[types.LambdaType,types.BuiltinFunctionType,
|
|
29
|
-
types.BuiltinMethodType,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
ClassMethodDescriptorType=types.ClassMethodDescriptorType
|
|
33
|
-
else: # 3.7之前的旧版本
|
|
34
|
-
ClassMethodDescriptorType=type(dict.__dict__['fromkeys'])
|
|
35
|
-
func_types.append(ClassMethodDescriptorType)
|
|
32
|
+
types.BuiltinMethodType,WrapperDescriptorType,
|
|
33
|
+
MethodWrapperType,MethodDescriptorType,
|
|
34
|
+
ClassMethodDescriptorType]
|
|
36
35
|
for type_ in func_types:
|
|
37
36
|
if isinstance(obj,type_):
|
|
38
37
|
return True
|
|
@@ -223,15 +222,19 @@ class ObjectBrowser():
|
|
|
223
222
|
self.tvw.item(self.functions_tag,open=True)
|
|
224
223
|
# 添加属性
|
|
225
224
|
attrs=dir(obj)
|
|
225
|
+
if isinstance(obj,type):
|
|
226
|
+
for attr in TYPE_EXTRA_ATTRS:
|
|
227
|
+
if hasattr(obj,attr):
|
|
228
|
+
attrs.append(attr) # 对类添加额外的,一般不会出现在dir()的返回值的属性
|
|
226
229
|
for i in range(len(attrs)):
|
|
227
230
|
attr=attrs[i]
|
|
228
231
|
if self.verbose or not attr.startswith("_"):
|
|
229
232
|
try:
|
|
230
|
-
|
|
231
|
-
value=_shortrepr(
|
|
232
|
-
image=self._get_image(
|
|
233
|
-
tags=("gray",) if isinstance(
|
|
234
|
-
self.tvw.insert(self._get_type(
|
|
233
|
+
object_=getattr(obj,attr)
|
|
234
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
235
|
+
image=self._get_image(object_)
|
|
236
|
+
tags=("gray",) if isinstance(object_,SKIP) else () # 将部分类型设为灰色,如MethodWrapperType
|
|
237
|
+
self.tvw.insert(self._get_type(object_), tk.END, #attr,
|
|
235
238
|
text=attr, image=image,
|
|
236
239
|
values=(value,),tags=tags) # values从第二列开始
|
|
237
240
|
except Exception as error: # 显示错误消息
|
|
@@ -239,20 +242,30 @@ class ObjectBrowser():
|
|
|
239
242
|
self.tvw.insert(self.attributes_tag, tk.END,
|
|
240
243
|
text=attr, image=self.obj_image,
|
|
241
244
|
values=(value,),tags=("error",))
|
|
242
|
-
#
|
|
243
|
-
if
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
# 添加类特有的属性 (不会在dir()出现)
|
|
246
|
+
if isinstance(obj,type):
|
|
247
|
+
for attr in TYPE_EXTRA_CLASS_ATTRS:
|
|
248
|
+
if not hasattr(obj,attr):continue
|
|
249
|
+
try:
|
|
250
|
+
object_=getattr(obj,attr)
|
|
251
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
252
|
+
self.tvw.insert(self.classes_tag, tk.END,
|
|
253
|
+
text=attr, image=self._get_image(object_),
|
|
254
|
+
values=(value,))
|
|
255
|
+
except Exception as error: # 显示错误
|
|
256
|
+
value='<{}: {}>'.format(type(error).__name__,str(error))
|
|
257
|
+
self.tvw.insert(self.classes_tag, tk.END,
|
|
258
|
+
text=attr, image=self.obj_image,
|
|
259
|
+
values=(value,),tags=("error",))
|
|
260
|
+
|
|
248
261
|
# 添加列表数据
|
|
249
262
|
if isinstance(obj,(list,tuple)):
|
|
250
263
|
for i in range(len(obj)):
|
|
251
264
|
index=str(i)
|
|
252
265
|
try:
|
|
253
|
-
|
|
254
|
-
value=_shortrepr(
|
|
255
|
-
image=self._get_image(
|
|
266
|
+
object_=obj[i]
|
|
267
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
268
|
+
image=self._get_image(object_)
|
|
256
269
|
self.tvw.insert(self.lst_tag, tk.END,
|
|
257
270
|
text=index, image=image,
|
|
258
271
|
values=(value,))
|
|
@@ -267,9 +280,9 @@ class ObjectBrowser():
|
|
|
267
280
|
for key in obj.keys():
|
|
268
281
|
key_name=repr(key)
|
|
269
282
|
try:
|
|
270
|
-
|
|
271
|
-
value=_shortrepr(
|
|
272
|
-
image=self._get_image(
|
|
283
|
+
object_=obj[key]
|
|
284
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
285
|
+
image=self._get_image(object_)
|
|
273
286
|
self.tvw.insert(self.dict_tag, tk.END,
|
|
274
287
|
text=key_name, image=image,
|
|
275
288
|
values=(value,))
|
|
@@ -420,11 +433,11 @@ class ObjectBrowser():
|
|
|
420
433
|
try:
|
|
421
434
|
# 对象的属性可能有改变,重新获取对象的属性
|
|
422
435
|
scope={self.rootobj_name:self.root_obj} # 获取第一个浏览的根对象及其名称
|
|
423
|
-
|
|
436
|
+
object_=eval(path,scope)
|
|
424
437
|
except Exception: # 默认使用新获取的对象,只有出错时,才使用旧的对象
|
|
425
|
-
|
|
426
|
-
else:
|
|
427
|
-
self.browse(
|
|
438
|
+
object_=obj
|
|
439
|
+
else:object_=obj
|
|
440
|
+
self.browse(object_,path)
|
|
428
441
|
def back(self): # 后退
|
|
429
442
|
if self.history_index!=0:
|
|
430
443
|
self.history_index-=1
|
|
@@ -204,6 +204,67 @@ PyObject *_list_setnull(PyObject *self, PyObject *args) {
|
|
|
204
204
|
Py_RETURN_NONE;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
static PyObject* get_type_flag(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
208
|
+
static char *kwlist[] = {"typeobj", NULL};
|
|
209
|
+
PyObject *typeobj;
|
|
210
|
+
|
|
211
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &typeobj))
|
|
212
|
+
return NULL;
|
|
213
|
+
|
|
214
|
+
PyTypeObject *type = (PyTypeObject *)typeobj;
|
|
215
|
+
unsigned long flags = type->tp_flags;
|
|
216
|
+
return PyLong_FromUnsignedLong(flags);
|
|
217
|
+
}
|
|
218
|
+
static PyObject* set_type_flag(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
219
|
+
static char *kwlist[] = {"typeobj", "flag", NULL};
|
|
220
|
+
PyObject *typeobj, *flag;
|
|
221
|
+
|
|
222
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &typeobj, &flag))
|
|
223
|
+
return NULL;
|
|
224
|
+
|
|
225
|
+
unsigned long new_flag = PyLong_AsUnsignedLong(flag);
|
|
226
|
+
PyTypeObject *type = (PyTypeObject *)typeobj;
|
|
227
|
+
type->tp_flags = new_flag;
|
|
228
|
+
Py_RETURN_NONE;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
static PyObject* set_type_base(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
232
|
+
static char *kwlist[] = {"typeobj", "base", NULL};
|
|
233
|
+
PyObject *typeobj, *base;
|
|
234
|
+
|
|
235
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &typeobj, &base))
|
|
236
|
+
return NULL;
|
|
237
|
+
|
|
238
|
+
Py_INCREF(base);
|
|
239
|
+
PyTypeObject *type = (PyTypeObject *)typeobj;
|
|
240
|
+
type->tp_base = base;
|
|
241
|
+
Py_RETURN_NONE;
|
|
242
|
+
}
|
|
243
|
+
static PyObject* set_type_bases(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
244
|
+
static char *kwlist[] = {"typeobj", "bases", NULL};
|
|
245
|
+
PyObject *typeobj, *bases;
|
|
246
|
+
|
|
247
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &typeobj, &bases))
|
|
248
|
+
return NULL;
|
|
249
|
+
|
|
250
|
+
Py_INCREF(bases);
|
|
251
|
+
PyTypeObject *type = (PyTypeObject *)typeobj;
|
|
252
|
+
type->tp_bases = bases;
|
|
253
|
+
Py_RETURN_NONE;
|
|
254
|
+
}
|
|
255
|
+
static PyObject* set_type_mro(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
256
|
+
static char *kwlist[] = {"typeobj", "mro", NULL};
|
|
257
|
+
PyObject *typeobj, *mro;
|
|
258
|
+
|
|
259
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &typeobj, &mro))
|
|
260
|
+
return NULL;
|
|
261
|
+
|
|
262
|
+
Py_INCREF(mro);
|
|
263
|
+
PyTypeObject *type = (PyTypeObject *)typeobj;
|
|
264
|
+
type->tp_mro = mro;
|
|
265
|
+
Py_RETURN_NONE;
|
|
266
|
+
}
|
|
267
|
+
|
|
207
268
|
/*
|
|
208
269
|
* List of functions to add to pyobj_extension in exec_pyobj_extension().
|
|
209
270
|
*/
|
|
@@ -216,7 +277,13 @@ static PyMethodDef pyobj_extension_functions[] = {
|
|
|
216
277
|
{ "getrefcount_nogil", (PyCFunction)getrefcount_nogil, METH_VARARGS, getrefcount_nogil_doc },
|
|
217
278
|
{ "setrefcount_nogil", (PyCFunction)setrefcount_nogil, METH_VARARGS | METH_KEYWORDS, setrefcount_nogil_doc },
|
|
218
279
|
{ "list_in", (PyCFunction)list_in, METH_VARARGS | METH_KEYWORDS, list_in_doc },
|
|
280
|
+
|
|
219
281
|
{ "_list_setnull", (PyCFunction)_list_setnull, METH_VARARGS, "_list_setnull(lst,index)"},
|
|
282
|
+
{"get_type_flag", (PyCFunction)get_type_flag, METH_VARARGS | METH_KEYWORDS, "get_type_flag(typeobj: type)"},
|
|
283
|
+
{"set_type_flag", (PyCFunction)set_type_flag, METH_VARARGS | METH_KEYWORDS, "set_type_flag(typeobj: type, flag: int)"},
|
|
284
|
+
{"set_type_base", (PyCFunction)set_type_base, METH_VARARGS | METH_KEYWORDS, "set_type_base(typeobj: type, base: type)"},
|
|
285
|
+
{"set_type_bases", (PyCFunction)set_type_bases, METH_VARARGS | METH_KEYWORDS, "set_type_bases(typeobj: type, bases: tuple)"},
|
|
286
|
+
{"set_type_mro", (PyCFunction)set_type_mro, METH_VARARGS | METH_KEYWORDS, "set_type_mro(typeobj: type, mro: tuple)"},
|
|
220
287
|
{ NULL, NULL, 0, NULL } /* marks end of array */
|
|
221
288
|
};
|
|
222
289
|
|
|
@@ -227,7 +294,7 @@ static PyMethodDef pyobj_extension_functions[] = {
|
|
|
227
294
|
int exec_pyobj_extension(PyObject *module) {
|
|
228
295
|
PyModule_AddFunctions(module, pyobj_extension_functions);
|
|
229
296
|
PyModule_AddStringConstant(module, "__author__", "qfcy");
|
|
230
|
-
PyModule_AddStringConstant(module, "__version__", "1.2.
|
|
297
|
+
PyModule_AddStringConstant(module, "__version__", "1.2.7");
|
|
231
298
|
PyModule_AddIntConstant(module, "_REFCNT_DELTA", REFCNT_DELTA);
|
|
232
299
|
|
|
233
300
|
return 0; /* success */
|
|
@@ -21,19 +21,18 @@ except ImportError:from __init__ import objectname,_shortrepr
|
|
|
21
21
|
_IMAGE_PATH=os.path.join(os.path.split(__file__)[0],"..","images")
|
|
22
22
|
SKIP=(WrapperDescriptorType, MethodWrapperType,\
|
|
23
23
|
MethodDescriptorType, ClassMethodDescriptorType)
|
|
24
|
+
TYPE_EXTRA_ATTRS = ("__basicsize__","__dictoffset__","__flags__",
|
|
25
|
+
"__itemsize__","__weakrefoffset__")
|
|
26
|
+
TYPE_EXTRA_CLASS_ATTRS = ("__base__","__bases__","__mro__")
|
|
24
27
|
|
|
25
28
|
def isfunc(obj):
|
|
26
29
|
# 判断一个对象是否为函数或方法
|
|
27
30
|
if isfunction(obj) or ismethod(obj):return True
|
|
28
31
|
# 使用typing而不用types.WrapperDescriptorType是为了与旧版本兼容
|
|
29
32
|
func_types=[types.LambdaType,types.BuiltinFunctionType,
|
|
30
|
-
types.BuiltinMethodType,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
ClassMethodDescriptorType=types.ClassMethodDescriptorType
|
|
34
|
-
else: # 3.7之前的旧版本
|
|
35
|
-
ClassMethodDescriptorType=type(dict.__dict__['fromkeys'])
|
|
36
|
-
func_types.append(ClassMethodDescriptorType)
|
|
33
|
+
types.BuiltinMethodType,WrapperDescriptorType,
|
|
34
|
+
MethodWrapperType,MethodDescriptorType,
|
|
35
|
+
ClassMethodDescriptorType]
|
|
37
36
|
for type_ in func_types:
|
|
38
37
|
if isinstance(obj,type_):
|
|
39
38
|
return True
|
|
@@ -148,7 +147,8 @@ class ObjectBrowser():
|
|
|
148
147
|
self.tvw.pack(side=tk.BOTTOM,expand=True,fill=tk.BOTH)
|
|
149
148
|
|
|
150
149
|
self.menu=tk.Menu(self.master,tearoff=False)
|
|
151
|
-
self.menu.add_command(label="新窗口打开",command=self.open_in_new_window,
|
|
150
|
+
self.menu.add_command(label="新窗口打开",command=self.open_in_new_window,
|
|
151
|
+
state=tk.DISABLED)
|
|
152
152
|
self.menu.add_command(label="新增属性",command=self.new_item,state=tk.DISABLED)
|
|
153
153
|
self.menu.add_command(label="删除",command=self.del_item,state=tk.DISABLED)
|
|
154
154
|
def on_rightclick(event):
|
|
@@ -214,7 +214,7 @@ class ObjectBrowser():
|
|
|
214
214
|
return self.classes_tag
|
|
215
215
|
else:return self.attributes_tag
|
|
216
216
|
def refresh(self,event=None,_first=False): # _first: 是否为初次加载
|
|
217
|
-
|
|
217
|
+
# 更新自身显示的数据
|
|
218
218
|
obj=self.obj
|
|
219
219
|
self.master.title("{} - {}".format(self.title,objectname(obj)))
|
|
220
220
|
self.label["text"]=" 路径: %s 对象: %s" % (self.name, _shortrepr(obj))
|
|
@@ -223,15 +223,19 @@ class ObjectBrowser():
|
|
|
223
223
|
self.tvw.item(self.functions_tag,open=True)
|
|
224
224
|
# 添加属性
|
|
225
225
|
attrs=dir(obj)
|
|
226
|
+
if isinstance(obj,type):
|
|
227
|
+
for attr in TYPE_EXTRA_ATTRS:
|
|
228
|
+
if hasattr(obj,attr):
|
|
229
|
+
attrs.append(attr) # 对类添加额外的,一般不会出现在dir()的返回值的属性
|
|
226
230
|
for i in range(len(attrs)):
|
|
227
231
|
attr=attrs[i]
|
|
228
232
|
if self.verbose or not attr.startswith("_"):
|
|
229
233
|
try:
|
|
230
|
-
|
|
231
|
-
value=_shortrepr(
|
|
232
|
-
image=self._get_image(
|
|
233
|
-
tags=("gray",) if isinstance(
|
|
234
|
-
self.tvw.insert(self._get_type(
|
|
234
|
+
object_=getattr(obj,attr)
|
|
235
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
236
|
+
image=self._get_image(object_)
|
|
237
|
+
tags=("gray",) if isinstance(object_,SKIP) else () # 将部分类型设为灰色,如MethodWrapperType
|
|
238
|
+
self.tvw.insert(self._get_type(object_), tk.END, #attr,
|
|
235
239
|
text=attr, image=image,
|
|
236
240
|
values=(value,),tags=tags) # values从第二列开始
|
|
237
241
|
except Exception as error: # 显示错误消息
|
|
@@ -239,20 +243,30 @@ class ObjectBrowser():
|
|
|
239
243
|
self.tvw.insert(self.attributes_tag, tk.END,
|
|
240
244
|
text=attr, image=self.obj_image,
|
|
241
245
|
values=(value,),tags=("error",))
|
|
242
|
-
#
|
|
243
|
-
if
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
# 添加类特有的属性 (不会在dir()出现)
|
|
247
|
+
if isinstance(obj,type):
|
|
248
|
+
for attr in TYPE_EXTRA_CLASS_ATTRS:
|
|
249
|
+
if not hasattr(obj,attr):continue
|
|
250
|
+
try:
|
|
251
|
+
object_=getattr(obj,attr)
|
|
252
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
253
|
+
self.tvw.insert(self.classes_tag, tk.END,
|
|
254
|
+
text=attr, image=self._get_image(object_),
|
|
255
|
+
values=(value,))
|
|
256
|
+
except Exception as error: # 显示错误
|
|
257
|
+
value='<{}: {}>'.format(type(error).__name__,str(error))
|
|
258
|
+
self.tvw.insert(self.classes_tag, tk.END,
|
|
259
|
+
text=attr, image=self.obj_image,
|
|
260
|
+
values=(value,),tags=("error",))
|
|
261
|
+
|
|
248
262
|
# 添加列表数据
|
|
249
263
|
if isinstance(obj,(list,tuple)):
|
|
250
264
|
for i in range(len(obj)):
|
|
251
265
|
index=str(i)
|
|
252
266
|
try:
|
|
253
|
-
|
|
254
|
-
value=_shortrepr(
|
|
255
|
-
image=self._get_image(
|
|
267
|
+
object_=obj[i]
|
|
268
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
269
|
+
image=self._get_image(object_)
|
|
256
270
|
self.tvw.insert(self.lst_tag, tk.END,
|
|
257
271
|
text=index, image=image,
|
|
258
272
|
values=(value,))
|
|
@@ -267,9 +281,9 @@ class ObjectBrowser():
|
|
|
267
281
|
for key in obj.keys():
|
|
268
282
|
key_name=repr(key)
|
|
269
283
|
try:
|
|
270
|
-
|
|
271
|
-
value=_shortrepr(
|
|
272
|
-
image=self._get_image(
|
|
284
|
+
object_=obj[key]
|
|
285
|
+
value=_shortrepr(object_,self.MAX_VIEW_LEN)
|
|
286
|
+
image=self._get_image(object_)
|
|
273
287
|
self.tvw.insert(self.dict_tag, tk.END,
|
|
274
288
|
text=key_name, image=image,
|
|
275
289
|
values=(value,))
|
|
@@ -420,11 +434,11 @@ class ObjectBrowser():
|
|
|
420
434
|
try:
|
|
421
435
|
# 对象的属性可能有改变,重新获取对象的属性
|
|
422
436
|
scope={self.rootobj_name:self.root_obj} # 获取第一个浏览的根对象及其名称
|
|
423
|
-
|
|
437
|
+
object_=eval(path,scope)
|
|
424
438
|
except Exception: # 默认使用新获取的对象,只有出错时,才使用旧的对象
|
|
425
|
-
|
|
426
|
-
else:
|
|
427
|
-
self.browse(
|
|
439
|
+
object_=obj
|
|
440
|
+
else:object_=obj
|
|
441
|
+
self.browse(object_,path)
|
|
428
442
|
def back(self): # 后退
|
|
429
443
|
if self.history_index!=0:
|
|
430
444
|
self.history_index-=1
|