update pyglet
fix fpslogger gone bug start using \viztracer/ modfied git ignore 啊啊啊
This commit is contained in:
parent
e1fdc5056e
commit
2bc9da9408
4
DR.py
4
DR.py
@ -4,6 +4,7 @@ mail: 3695888@qq.com
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import cProfile
|
||||
import traceback
|
||||
|
||||
@ -42,6 +43,7 @@ if __name__ == '__main__':
|
||||
from Difficult_Rocket.api.Exp import *
|
||||
from Difficult_Rocket.crash import crash
|
||||
try:
|
||||
start_time = time.perf_counter_ns()
|
||||
import pyglet
|
||||
pyglet.options["win32_gdi_font"] = True
|
||||
|
||||
@ -52,6 +54,8 @@ if __name__ == '__main__':
|
||||
|
||||
game = main.Game()
|
||||
|
||||
print(time.perf_counter_ns() - start_time)
|
||||
|
||||
cprofile = False
|
||||
if cprofile:
|
||||
cProfile.run('game.start()', sort='calls')
|
||||
|
@ -11,24 +11,15 @@ github: @shenjackyuanjie
|
||||
gitee: @shenjackyuanjie
|
||||
"""
|
||||
|
||||
__all__ = ['TexturesError',
|
||||
'LanguageError',
|
||||
'TestError']
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""基础 Exception"""
|
||||
def __bool__(self):
|
||||
return False
|
||||
from Difficult_Rocket.api.Exp.main import Error
|
||||
from Difficult_Rocket.api.Exp.command import CommandError, CommandParseError, CommandQMarkPosError, \
|
||||
CommandQMarkConflict, CommandQMarkMissing, CommandQMarkPreMissing, CommandQMarkSufMissing
|
||||
from Difficult_Rocket.api.Exp.unsupport import NoMoreJson5
|
||||
|
||||
|
||||
class TexturesError(Error):
|
||||
"""材质相关 error"""
|
||||
|
||||
|
||||
class LanguageError(Error):
|
||||
"""语言相关 error"""
|
||||
|
||||
|
||||
class TestError(Error):
|
||||
"""就像名字一样 用于测试的 error"""
|
||||
|
15
Difficult_Rocket/api/Exp/language.py
Normal file
15
Difficult_Rocket/api/Exp/language.py
Normal file
@ -0,0 +1,15 @@
|
||||
# -------------------------------
|
||||
# Difficult Rocket
|
||||
# Copyright © 2021-2022 by shenjackyuanjie
|
||||
# All rights reserved
|
||||
# -------------------------------
|
||||
|
||||
from Difficult_Rocket.api.Exp import Error
|
||||
|
||||
|
||||
class LanguageError(Error):
|
||||
"""语言相关 error"""
|
||||
|
||||
|
||||
class TranslateFileNotFoundError(LanguageError):
|
||||
"""某个语言的翻译文件未找到"""
|
18
Difficult_Rocket/api/Exp/main.py
Normal file
18
Difficult_Rocket/api/Exp/main.py
Normal file
@ -0,0 +1,18 @@
|
||||
# -------------------------------
|
||||
# Difficult Rocket
|
||||
# Copyright © 2021-2022 by shenjackyuanjie
|
||||
# All rights reserved
|
||||
# -------------------------------
|
||||
|
||||
"""
|
||||
writen by shenjackyuanjie
|
||||
mail: 3695888@qq.com
|
||||
github: @shenjackyuanjie
|
||||
gitee: @shenjackyuanjie
|
||||
"""
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""基础 Exception"""
|
||||
def __bool__(self):
|
||||
return False
|
22
Difficult_Rocket/api/Exp/unsupport.py
Normal file
22
Difficult_Rocket/api/Exp/unsupport.py
Normal file
@ -0,0 +1,22 @@
|
||||
# -------------------------------
|
||||
# Difficult Rocket
|
||||
# Copyright © 2021-2022 by shenjackyuanjie
|
||||
# All rights reserved
|
||||
# -------------------------------
|
||||
|
||||
"""
|
||||
writen by shenjackyuanjie
|
||||
mail: 3695888@qq.com
|
||||
github: @shenjackyuanjie
|
||||
gitee: @shenjackyuanjie
|
||||
"""
|
||||
|
||||
from Difficult_Rocket.api.Exp.main import Error
|
||||
|
||||
|
||||
class NoMoreJson5(Error):
|
||||
"""说什么我也不用Json5了!"""
|
||||
|
||||
|
||||
class NopeImTeapot418(Error):
|
||||
"""我只是个茶壶而已,我不能煮咖啡!"""
|
@ -13,9 +13,7 @@ gitee: @shenjackyuanjie
|
||||
|
||||
# system function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import ctypes
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
@ -135,7 +133,7 @@ class ClientWindow(Window):
|
||||
multiline=True,
|
||||
batch=self.label_batch, group=self.command_group)
|
||||
# 设置刷新率
|
||||
pyglet.clock.schedule_interval(self.update, float(self.SPF))
|
||||
pyglet.clock.schedule(self.draw_update)
|
||||
# 完成设置后的信息输出
|
||||
self.logger.info(tr.lang('window', 'setup.done'))
|
||||
self.logger.info(tr.lang('window', 'os.pid_is').format(os.getpid(), os.getppid()))
|
||||
@ -143,6 +141,7 @@ class ClientWindow(Window):
|
||||
self.use_time = end_time - start_time
|
||||
self.logger.info(tr.lang('window', 'setup.use_time').format(Decimal(self.use_time) / 1000000000))
|
||||
self.logger.debug(tr.lang('window', 'setup.use_time_ns').format(self.use_time))
|
||||
self.count = 0
|
||||
|
||||
def setup(self):
|
||||
self.load_fonts()
|
||||
@ -159,8 +158,8 @@ class ClientWindow(Window):
|
||||
|
||||
def start_game(self) -> None:
|
||||
self.run_input = True
|
||||
# self.read_input()
|
||||
pyglet.app.run()
|
||||
self.read_input()
|
||||
pyglet.app.event_loop.run(1/self.main_config['runtime']['fps'])
|
||||
|
||||
@new_thread('window read_input', daemon=True)
|
||||
def read_input(self):
|
||||
@ -190,15 +189,21 @@ class ClientWindow(Window):
|
||||
draws and some event
|
||||
"""
|
||||
|
||||
def update(self, tick: float):
|
||||
def draw_update(self, tick: float):
|
||||
self.count += 1
|
||||
if self.count >= 100:
|
||||
try:
|
||||
self.count = 0
|
||||
self.logger.debug(tick)
|
||||
self.logger.debug('update! {} {}'.format(tick, pyglet.clock.get_frequency()))
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
decimal_tick = Decimal(str(tick)[:10])
|
||||
self.FPS_update(decimal_tick)
|
||||
self.fps_log.update_tick(Decimal(tick))
|
||||
|
||||
def FPS_update(self, tick: Decimal):
|
||||
now_FPS = pyglet.clock.get_frequency()
|
||||
self.fps_log.update_tick(tick)
|
||||
|
||||
self.fps_log.update_tick(now_FPS, tick)
|
||||
self.fps_label.text = f'FPS: {self.fps_log.fps: >5.1f}({self.fps_log.middle_fps: >5.1f})[{now_FPS: >.7f}]\n {self.fps_log.max_fps: >7.1f} {self.fps_log.min_fps:>5.1f}'
|
||||
|
||||
def on_draw(self, *dt):
|
||||
@ -210,6 +215,9 @@ class ClientWindow(Window):
|
||||
super().on_resize(width, height)
|
||||
self.fps_label.y = height - 10
|
||||
|
||||
def on_refresh(self, dt):
|
||||
...
|
||||
|
||||
def draw_batch(self):
|
||||
self.part_batch.draw()
|
||||
self.label_batch.draw()
|
||||
@ -221,6 +229,9 @@ class ClientWindow(Window):
|
||||
def on_command(self, command: line.CommandText):
|
||||
self.logger.info(tr.lang('window', 'command.text').format(command))
|
||||
if command.match('stop'):
|
||||
self.is_running = False
|
||||
self.dispatch_event('on_exit')
|
||||
platform_event_loop.stop()
|
||||
self.dispatch_event('on_close', 'command') # source = command
|
||||
elif command.match('fps'):
|
||||
if command.match('log'):
|
||||
|
@ -17,8 +17,6 @@ import statistics
|
||||
from typing import Union
|
||||
from decimal import Decimal
|
||||
|
||||
from libs.pyglet.clock import get_frequency
|
||||
|
||||
|
||||
class FpsLogger:
|
||||
def __init__(self,
|
||||
@ -34,12 +32,15 @@ class FpsLogger:
|
||||
self._min_fps = stable_fps
|
||||
|
||||
def update_tick(self,
|
||||
pyglet_fps: float,
|
||||
tick: Decimal):
|
||||
now_fps = get_frequency()
|
||||
if now_fps != 0:
|
||||
self.fps_list.append(now_fps)
|
||||
if pyglet_fps != 0:
|
||||
self.fps_list.append(pyglet_fps)
|
||||
else:
|
||||
self.fps_list.append(1)
|
||||
if tick != 0:
|
||||
self.fps_list.append(float(1 / tick))
|
||||
else:
|
||||
self.fps_list.append(1)
|
||||
if len(self.fps_list) > self.count:
|
||||
self.fps_list = self.fps_list[-self.count + 1:] # 整个列表往前挪一位
|
||||
if len(self.get_fps_list) > self.count:
|
||||
|
@ -14,6 +14,11 @@ gitee: @shenjackyuanjie
|
||||
from Difficult_Rocket import game_version
|
||||
from Difficult_Rocket.command import line
|
||||
|
||||
|
||||
class Command:
|
||||
"""一个空类 用于标记命令信息"""
|
||||
|
||||
|
||||
COMMAND = 'command'
|
||||
SUB_COMMAND = 'sub_command'
|
||||
INFO = 'info'
|
||||
|
@ -18,13 +18,15 @@ import logging
|
||||
import logging.config
|
||||
import multiprocessing
|
||||
|
||||
import pyglet.clock
|
||||
|
||||
if __name__ == '__main__': # been start will not run this
|
||||
sys.path.append('/bin/libs')
|
||||
sys.path.append('/bin')
|
||||
|
||||
from Difficult_Rocket import client, server
|
||||
from utils import tools
|
||||
from utils.translate import tr
|
||||
from Difficult_Rocket.utils import tools
|
||||
from Difficult_Rocket.utils.translate import tr
|
||||
|
||||
|
||||
class Game:
|
||||
@ -37,7 +39,7 @@ class Game:
|
||||
self.language = tools.load_file('configs/main.config', 'runtime')['language']
|
||||
tr.set_language(self.language)
|
||||
# logging config
|
||||
log_config = tools.load_file('configs/logger.json5')
|
||||
log_config = tools.load_file('configs/logger.toml')
|
||||
file_name = log_config['handlers']['file']['filename']
|
||||
del log_config['handlers']['file']['datefmt']
|
||||
log_config['handlers']['file']['filename'] = f'logs/{file_name.format(self.start_time)}'
|
||||
@ -56,6 +58,7 @@ class Game:
|
||||
|
||||
def setup(self) -> None:
|
||||
self.client = client.Client(net_mode='local')
|
||||
pyglet.clock.schedule(self.client.window.draw_update)
|
||||
self.server = server.Server(net_mode='local')
|
||||
|
||||
def python_version_check(self) -> None: # best 3.8+ and write at 3.8.10
|
||||
|
@ -43,5 +43,6 @@ class Server:
|
||||
self.net_mode = net_mode
|
||||
self.logger.info(tr.lang('server', 'setup.done'))
|
||||
|
||||
@new_thread('Server')
|
||||
def run(self):
|
||||
self.logger.info(tr.lang('server', 'os.pid_is').format(os.getpid(), os.getppid()))
|
||||
|
@ -15,20 +15,14 @@ import os
|
||||
import sys
|
||||
import time
|
||||
import math
|
||||
import decimal
|
||||
import logging
|
||||
import configparser
|
||||
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
if __name__ == '__main__': # 如果是直接运行该文件,则将工作目录切换到该文件所在目录
|
||||
sys.path.append('./libs')
|
||||
sys.path.append('./')
|
||||
|
||||
import toml
|
||||
|
||||
from libs import json5
|
||||
from libs import toml
|
||||
|
||||
from Difficult_Rocket.api.Exp import NoMoreJson5
|
||||
# logger
|
||||
tools_logger = logging.getLogger('part-tools')
|
||||
"""
|
||||
@ -44,17 +38,7 @@ def load_file(file_name: str, stack=None):
|
||||
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
|
||||
try:
|
||||
get_file = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!')
|
||||
if (f_type == 'json5') or (f_type == 'json'):
|
||||
try:
|
||||
with open(file_name, 'r', encoding='utf-8') as jf: # jf -> json file
|
||||
get_file = json5.load(jf, encoding='uft-8')
|
||||
except UnicodeDecodeError:
|
||||
with open(file_name, 'r', encoding='gbk') as jf:
|
||||
get_file = json5.load(jf)
|
||||
tools_logger.info('文件 %s 解码错误,已重新使用gbk编码打开' % file_name)
|
||||
if stack is not None:
|
||||
get_file = get_file[stack]
|
||||
elif f_type == 'xml':
|
||||
if f_type == 'xml':
|
||||
xml_load = parse(file_name)
|
||||
if stack is not None:
|
||||
get_file = xml_load.getElementsByTagName(stack)
|
||||
@ -65,6 +49,8 @@ def load_file(file_name: str, stack=None):
|
||||
get_file = get_file[stack]
|
||||
elif f_type == 'toml':
|
||||
get_file = toml.load(file_name)
|
||||
elif f_type == 'json5':
|
||||
raise NoMoreJson5("我说什么也不用json5了!喵的")
|
||||
except Exception as exp:
|
||||
error_type = type(exp).__name__
|
||||
if error_type in file_error:
|
||||
@ -83,7 +69,7 @@ def get_At(name, in_xml, need_type=str):
|
||||
"""
|
||||
get Attribute from a XML tree
|
||||
will raise TypeError if input is not str or list
|
||||
XML no! Json5 yes!
|
||||
XML json5 no! toml yes!
|
||||
"""
|
||||
name_type = type(name)
|
||||
if name_type == list:
|
||||
|
@ -3,7 +3,7 @@
|
||||
IFS=$'\n';
|
||||
|
||||
# 默认值是 10个 可以一次性展示更多 就修改第15行代码 | head -n 30 或者更多
|
||||
objects=`git verify-pack -v .git/objects/pack/pack-aba4bfc55979194c86dbd466c86e57d8199ae7ad.idx | grep -v chain | sort -k3nr | head -n 50`
|
||||
objects=`git verify-pack -v .git/objects/pack/pack-aba4bfc55979194c86dbd466c86e57d8199ae7ad.idx | grep -v chain | sort -k3nr | head -n 100`
|
||||
|
||||
echo "All sizes are in kB. The pack column is the size of the object, compressed, inside the pack file."
|
||||
|
||||
@ -23,3 +23,5 @@ do
|
||||
done
|
||||
|
||||
echo -e $output | column -t -s ', '
|
||||
|
||||
pause
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
'version': 1,
|
||||
'formatters': {
|
||||
'file': { // file 跟 root 的输出格式一致
|
||||
'file': {
|
||||
'class': 'logging.Formatter',
|
||||
'format': '[%(asctime)s][%(name)s]:[%(levelname)s] %(message)s',
|
||||
'datefmt': '%Y-%m-%d %H-%M-%S'
|
||||
|
46
configs/logger.toml
Normal file
46
configs/logger.toml
Normal file
@ -0,0 +1,46 @@
|
||||
version = 1
|
||||
|
||||
[root]
|
||||
level = "DEBUG"
|
||||
handlers = [ "console", "file"]
|
||||
|
||||
[formatters.file]
|
||||
class = "logging.Formatter"
|
||||
format = "[%(asctime)s][%(name)s]:[%(levelname)s] %(message)s"
|
||||
datefmt = "%Y-%m-%d %H-%M-%S"
|
||||
|
||||
[formatters.client]
|
||||
class = "logging.Formatter"
|
||||
format = "[%(asctime)s][%(name)s]:[%(levelname)s] %(message)s"
|
||||
datefmt = "%Y-%m-%d %H-%M-%S"
|
||||
|
||||
[formatters.server]
|
||||
class = "logging.Formatter"
|
||||
format = "[%(asctime)s][%(name)s]:[%(levelname)s] %(message)s"
|
||||
datefmt = "%Y-%m-%d %H-%M-%S"
|
||||
|
||||
[handlers.console]
|
||||
class = "logging.StreamHandler"
|
||||
formatter = "file"
|
||||
level = "DEBUG"
|
||||
|
||||
[handlers.file]
|
||||
class = "logging.FileHandler"
|
||||
filename = "{} DR.log"
|
||||
datefmt = "%Y-%m-%d %H-%M-%S"
|
||||
encoding = "utf-8"
|
||||
formatter = "file"
|
||||
level = "DEBUG"
|
||||
mode = "w"
|
||||
|
||||
[loggers.client]
|
||||
level = "DEBUG"
|
||||
handlers = []
|
||||
|
||||
[loggers.server]
|
||||
level = "DEBUG"
|
||||
handlers = []
|
||||
|
||||
[loggers.main]
|
||||
level = "DEBUG"
|
||||
handlers = []
|
@ -8,8 +8,8 @@ fonts_folder = "libs/fonts"
|
||||
|
||||
[window]
|
||||
style = "None"
|
||||
width = 1300
|
||||
height = 931
|
||||
width = 1139
|
||||
height = 1145
|
||||
visible = true
|
||||
caption = "Difficult Rocket {version}"
|
||||
resizable = true
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -1,26 +0,0 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""A pure Python implementation of the JSON5 configuration language."""
|
||||
|
||||
from .lib import load, loads, dump, dumps
|
||||
from .version import VERSION
|
||||
|
||||
__all__ = [
|
||||
'VERSION',
|
||||
'dump',
|
||||
'dumps',
|
||||
'load',
|
||||
'loads',
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys # pragma: no cover
|
||||
|
||||
from .tool import main # pragma: no cover
|
||||
|
||||
if __name__ == '__main__': # pragma: no cover
|
||||
sys.exit(main())
|
@ -1,61 +0,0 @@
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
|
||||
|
||||
class _Bailout(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ArgumentParser(argparse.ArgumentParser):
|
||||
SUPPRESS = argparse.SUPPRESS
|
||||
|
||||
def __init__(self, host, prog, desc, **kwargs):
|
||||
kwargs['prog'] = prog
|
||||
kwargs['description'] = desc
|
||||
kwargs['formatter_class'] = argparse.RawDescriptionHelpFormatter
|
||||
super(ArgumentParser, self).__init__(**kwargs)
|
||||
self._host = host
|
||||
self.exit_status = None
|
||||
self.add_argument('-V', '--version', action='store_true',
|
||||
help='print the version and exit')
|
||||
|
||||
def parse_args(self, args=None, namespace=None):
|
||||
try:
|
||||
rargs = super(ArgumentParser, self).parse_args(args=args,
|
||||
namespace=namespace)
|
||||
except _Bailout:
|
||||
return None
|
||||
|
||||
return rargs
|
||||
|
||||
# Redefining built-in 'file' pylint: disable=W0622
|
||||
|
||||
def _print_message(self, msg, file=None):
|
||||
self._host.print_(msg=msg, stream=file, end='\n')
|
||||
|
||||
def print_help(self, file=None):
|
||||
self._print_message(msg=self.format_help(), file=file)
|
||||
|
||||
def error(self, message, bailout=True): # pylint: disable=W0221
|
||||
self.exit(2, '%s: error: %s\n' % (self.prog, message), bailout=bailout)
|
||||
|
||||
def exit(self, status=0, message=None, # pylint: disable=W0221
|
||||
bailout=True):
|
||||
self.exit_status = status
|
||||
if message:
|
||||
self._print_message(message, file=self._host.stderr)
|
||||
if bailout:
|
||||
raise _Bailout()
|
@ -1,57 +0,0 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
# pylint: disable=redefined-builtin, invalid-name
|
||||
str = unicode
|
||||
|
||||
|
||||
class Host(object):
|
||||
def __init__(self):
|
||||
self.stdin = sys.stdin
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
|
||||
def chdir(self, *comps):
|
||||
return os.chdir(self.join(*comps))
|
||||
|
||||
def getcwd(self):
|
||||
return os.getcwd()
|
||||
|
||||
def join(self, *comps):
|
||||
return os.path.join(*comps)
|
||||
|
||||
def mkdtemp(self, **kwargs):
|
||||
return tempfile.mkdtemp(**kwargs)
|
||||
|
||||
def print_(self, msg=u'', end=u'\n', stream=None):
|
||||
stream = stream or self.stdout
|
||||
stream.write(str(msg) + end)
|
||||
stream.flush()
|
||||
|
||||
def rmtree(self, path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
def read_text_file(self, path):
|
||||
with open(path, 'rb') as fp:
|
||||
return fp.read().decode('utf8')
|
||||
|
||||
def write_text_file(self, path, contents):
|
||||
with open(path, 'wb') as f:
|
||||
f.write(contents.encode('utf8'))
|
@ -1,511 +0,0 @@
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
from .parser import Parser
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
str_types = (str, unicode)
|
||||
str = unicode # pylint: disable=redefined-builtin, invalid-name
|
||||
else:
|
||||
str_types = (str,)
|
||||
long = int # pylint: disable=redefined-builtin, invalid-name
|
||||
|
||||
|
||||
def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
|
||||
parse_int=None, parse_constant=None, object_pairs_hook=None,
|
||||
allow_duplicate_keys=True):
|
||||
"""Deserialize ``fp`` (a ``.read()``-supporting file-like object
|
||||
containing a JSON document) to a Python object.
|
||||
|
||||
Supports almost the same arguments as ``json.load()`` except that:
|
||||
- the `cls` keyword is ignored.
|
||||
- an extra `allow_duplicate_keys` parameter supports checking for
|
||||
duplicate keys in a object; by default, this is True for
|
||||
compatibility with ``json.load()``, but if set to False and
|
||||
the object contains duplicate keys, a ValueError will be raised.
|
||||
"""
|
||||
|
||||
s = fp.read()
|
||||
return loads(s, encoding=encoding, cls=cls, object_hook=object_hook,
|
||||
parse_float=parse_float, parse_int=parse_int,
|
||||
parse_constant=parse_constant,
|
||||
object_pairs_hook=object_pairs_hook,
|
||||
allow_duplicate_keys=allow_duplicate_keys)
|
||||
|
||||
|
||||
def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
|
||||
parse_int=None, parse_constant=None, object_pairs_hook=None,
|
||||
allow_duplicate_keys=True):
|
||||
"""Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a
|
||||
JSON5 document) to a Python object.
|
||||
|
||||
Supports the same arguments as ``json.load()`` except that:
|
||||
- the `cls` keyword is ignored.
|
||||
- an extra `allow_duplicate_keys` parameter supports checking for
|
||||
duplicate keys in a object; by default, this is True for
|
||||
compatibility with ``json.load()``, but if set to False and
|
||||
the object contains duplicate keys, a ValueError will be raised.
|
||||
"""
|
||||
|
||||
assert cls is None, 'Custom decoders are not supported'
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
decodable_type = type('')
|
||||
else:
|
||||
decodable_type = type(b'')
|
||||
if isinstance(s, decodable_type):
|
||||
encoding = encoding or 'utf-8'
|
||||
s = s.decode(encoding)
|
||||
|
||||
if not s:
|
||||
raise ValueError('Empty strings are not legal JSON5')
|
||||
parser = Parser(s, '<string>')
|
||||
ast, err, _ = parser.parse()
|
||||
if err:
|
||||
raise ValueError(err)
|
||||
|
||||
def _fp_constant_parser(s):
|
||||
return float(s.replace('Infinity', 'inf').replace('NaN', 'nan'))
|
||||
|
||||
if object_pairs_hook:
|
||||
dictify = object_pairs_hook
|
||||
elif object_hook:
|
||||
dictify = lambda pairs: object_hook(dict(pairs))
|
||||
else:
|
||||
dictify = lambda pairs: dict(pairs) # pylint: disable=unnecessary-lambda
|
||||
|
||||
if not allow_duplicate_keys:
|
||||
_orig_dictify = dictify
|
||||
dictify = lambda pairs: _reject_duplicate_keys(pairs, _orig_dictify)
|
||||
|
||||
parse_float = parse_float or float
|
||||
parse_int = parse_int or int
|
||||
parse_constant = parse_constant or _fp_constant_parser
|
||||
|
||||
return _walk_ast(ast, dictify, parse_float, parse_int, parse_constant)
|
||||
|
||||
|
||||
def _reject_duplicate_keys(pairs, dictify):
|
||||
keys = set()
|
||||
for key, _ in pairs:
|
||||
if key in keys:
|
||||
raise ValueError('Duplicate key "%s" found in object', key)
|
||||
keys.add(key)
|
||||
return dictify(pairs)
|
||||
|
||||
|
||||
def _walk_ast(el, dictify, parse_float, parse_int, parse_constant):
|
||||
if el == 'None':
|
||||
return None
|
||||
if el == 'True':
|
||||
return True
|
||||
if el == 'False':
|
||||
return False
|
||||
ty, v = el
|
||||
if ty == 'number':
|
||||
if v.startswith('0x') or v.startswith('0X'):
|
||||
return parse_int(v, base=16)
|
||||
elif '.' in v or 'e' in v or 'E' in v:
|
||||
return parse_float(v)
|
||||
elif 'Infinity' in v or 'NaN' in v:
|
||||
return parse_constant(v)
|
||||
else:
|
||||
return parse_int(v)
|
||||
if ty == 'string':
|
||||
return v
|
||||
if ty == 'object':
|
||||
pairs = []
|
||||
for key, val_expr in v:
|
||||
val = _walk_ast(val_expr, dictify, parse_float, parse_int,
|
||||
parse_constant)
|
||||
pairs.append((key, val))
|
||||
return dictify(pairs)
|
||||
if ty == 'array':
|
||||
return [_walk_ast(el, dictify, parse_float, parse_int, parse_constant)
|
||||
for el in v]
|
||||
raise Exception('unknown el: ' + el) # pragma: no cover
|
||||
|
||||
|
||||
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||
allow_nan=True, cls=None, indent=None, separators=None,
|
||||
default=None, sort_keys=False,
|
||||
quote_keys=False, trailing_commas=True,
|
||||
allow_duplicate_keys=True,
|
||||
**kwargs):
|
||||
"""Serialize ``obj`` to a JSON5-formatted stream to ``fp`` (a ``.write()``-
|
||||
supporting file-like object).
|
||||
|
||||
Supports the same arguments as ``json.dumps()``, except that:
|
||||
|
||||
- The ``cls`` keyword is not supported.
|
||||
- The ``encoding`` keyword is ignored; Unicode strings are always written.
|
||||
- By default, object keys that are legal identifiers are not quoted;
|
||||
if you pass quote_keys=True, they will be.
|
||||
- By default, if lists and objects span multiple lines of output (i.e.,
|
||||
when ``indent`` >=0), the last item will have a trailing comma
|
||||
after it. If you pass ``trailing_commas=False, it will not.
|
||||
- If you use a number, a boolean, or None as a key value in a dict,
|
||||
it will be converted to the corresponding json string value, e.g.
|
||||
"1", "true", or "null". By default, dump() will match the `json`
|
||||
modules behavior and produce ill-formed JSON if you mix keys of
|
||||
different types that have the same converted value, e.g.:
|
||||
{1: "foo", "1": "bar"} produces '{"1": "foo", "1": "bar"}', an
|
||||
object with duplicated keys. If you pass allow_duplicate_keys=False,
|
||||
an exception will be raised instead.
|
||||
|
||||
Calling ``dumps(obj, fp, quote_keys=True, trailing_commas=False,
|
||||
allow_duplicate_keys=True)``
|
||||
should produce exactly the same output as ``json.dumps(obj, fp).``
|
||||
"""
|
||||
|
||||
fp.write(str(dumps(obj=obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii,
|
||||
check_circular=check_circular, allow_nan=allow_nan,
|
||||
cls=cls, indent=indent, separators=separators,
|
||||
default=default, sort_keys=sort_keys,
|
||||
quote_keys=quote_keys, trailing_commas=trailing_commas,
|
||||
allow_duplicate_keys=allow_duplicate_keys)))
|
||||
|
||||
|
||||
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||
allow_nan=True, cls=None, indent=None, separators=None,
|
||||
default=None, sort_keys=False,
|
||||
quote_keys=False, trailing_commas=True, allow_duplicate_keys=True,
|
||||
**kwargs):
|
||||
"""Serialize ``obj`` to a JSON5-formatted ``str``.
|
||||
|
||||
Supports the same arguments as ``json.dumps()``, except that:
|
||||
|
||||
- The ``cls`` keyword is not supported.
|
||||
- The ``encoding`` keyword is ignored; Unicode strings are always returned.
|
||||
- By default, object keys that are legal identifiers are not quoted;
|
||||
if you pass quote_keys=True, they will be.
|
||||
- By default, if lists and objects span multiple lines of output (i.e.,
|
||||
when ``indent`` >=0), the last item will have a trailing comma
|
||||
after it. If you pass ``trailing_commas=False, it will not.
|
||||
- If you use a number, a boolean, or None as a key value in a dict,
|
||||
it will be converted to the corresponding json string value, e.g.
|
||||
"1", "true", or "null". By default, dump() will match the ``json``
|
||||
module's behavior and produce ill-formed JSON if you mix keys of
|
||||
different types that have the same converted value, e.g.:
|
||||
{1: "foo", "1": "bar"} produces '{"1": "foo", "1": "bar"}', an
|
||||
object with duplicated keys. If you pass ``allow_duplicate_keys=False``,
|
||||
an exception will be raised instead.
|
||||
|
||||
|
||||
Calling ``dumps(obj, quote_keys=True, trailing_commas=False,
|
||||
allow_duplicate_keys=True)``
|
||||
should produce exactly the same output as ``json.dumps(obj).``
|
||||
"""
|
||||
|
||||
assert kwargs.get('cls', None) is None, 'Custom encoders are not supported'
|
||||
|
||||
if separators is None:
|
||||
if indent is None:
|
||||
separators = (u', ', u': ')
|
||||
else:
|
||||
separators = (u',', u': ')
|
||||
|
||||
default = default or _raise_type_error
|
||||
|
||||
if check_circular:
|
||||
seen = set()
|
||||
else:
|
||||
seen = None
|
||||
|
||||
level = 1
|
||||
is_key = False
|
||||
|
||||
_, v = _dumps(obj, skipkeys, ensure_ascii, check_circular,
|
||||
allow_nan, indent, separators, default, sort_keys,
|
||||
quote_keys, trailing_commas, allow_duplicate_keys,
|
||||
seen, level, is_key)
|
||||
return v
|
||||
|
||||
|
||||
def _dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, indent,
|
||||
separators, default, sort_keys,
|
||||
quote_keys, trailing_commas, allow_duplicate_keys,
|
||||
seen, level, is_key):
|
||||
if obj is True:
|
||||
s = u'true'
|
||||
elif obj is False:
|
||||
s = u'false'
|
||||
elif obj is None:
|
||||
s = u'null'
|
||||
elif isinstance(obj, str_types):
|
||||
if (is_key and _is_ident(obj) and not quote_keys
|
||||
and not _is_reserved_word(obj)):
|
||||
return True, obj
|
||||
return True, _dump_str(obj, ensure_ascii)
|
||||
elif isinstance(obj, float):
|
||||
s = _dump_float(obj, allow_nan)
|
||||
elif isinstance(obj, int):
|
||||
s = str(obj)
|
||||
else:
|
||||
s = None
|
||||
|
||||
if is_key:
|
||||
if s is not None:
|
||||
return True, '"%s"' % s
|
||||
if skipkeys:
|
||||
return False, None
|
||||
raise TypeError('invalid key %s' % repr(obj))
|
||||
|
||||
if s is not None:
|
||||
return True, s
|
||||
|
||||
if indent is not None:
|
||||
end_str = ''
|
||||
if trailing_commas:
|
||||
end_str = ','
|
||||
if type(indent) == int:
|
||||
if indent > 0:
|
||||
indent_str = '\n' + ' ' * indent * level
|
||||
end_str += '\n' + ' ' * indent * (level - 1)
|
||||
else:
|
||||
indent_str = '\n'
|
||||
end_str += '\n'
|
||||
else:
|
||||
indent_str = '\n' + indent * level
|
||||
end_str += '\n' + indent * (level - 1)
|
||||
else:
|
||||
indent_str = ''
|
||||
end_str = ''
|
||||
|
||||
item_sep, kv_sep = separators
|
||||
item_sep += indent_str
|
||||
level += 1
|
||||
|
||||
if seen is not None:
|
||||
i = id(obj)
|
||||
if i in seen:
|
||||
raise ValueError('Circular reference detected.')
|
||||
else:
|
||||
seen.add(i)
|
||||
|
||||
# In Python3, we'd check if this was an abc.Mapping or an abc.Sequence.
|
||||
# For now, just check for the attrs we need to iterate over the object.
|
||||
if hasattr(obj, 'keys') and hasattr(obj, '__getitem__'):
|
||||
s = _dump_dict(obj, skipkeys, ensure_ascii,
|
||||
check_circular, allow_nan, indent,
|
||||
separators, default, sort_keys,
|
||||
quote_keys, trailing_commas,
|
||||
allow_duplicate_keys, seen, level,
|
||||
item_sep, kv_sep, indent_str, end_str)
|
||||
elif hasattr(obj, '__getitem__') and hasattr(obj, '__iter__'):
|
||||
s = _dump_array(obj, skipkeys, ensure_ascii,
|
||||
check_circular, allow_nan, indent,
|
||||
separators, default, sort_keys,
|
||||
quote_keys, trailing_commas,
|
||||
allow_duplicate_keys, seen, level,
|
||||
item_sep, indent_str, end_str)
|
||||
else:
|
||||
s = default(obj)
|
||||
|
||||
if seen is not None:
|
||||
seen.remove(i)
|
||||
return False, s
|
||||
|
||||
|
||||
def _dump_dict(obj, skipkeys, ensure_ascii, check_circular, allow_nan,
|
||||
indent, separators, default, sort_keys,
|
||||
quote_keys, trailing_commas, allow_duplicate_keys,
|
||||
seen, level, item_sep, kv_sep, indent_str, end_str):
|
||||
if not obj:
|
||||
return u'{}'
|
||||
|
||||
if sort_keys:
|
||||
keys = sorted(obj.keys())
|
||||
else:
|
||||
keys = obj.keys()
|
||||
|
||||
s = u'{' + indent_str
|
||||
|
||||
num_items_added = 0
|
||||
new_keys = set()
|
||||
for key in keys:
|
||||
valid_key, key_str = _dumps(key, skipkeys, ensure_ascii, check_circular,
|
||||
allow_nan, indent, separators, default,
|
||||
sort_keys,
|
||||
quote_keys, trailing_commas,
|
||||
allow_duplicate_keys,
|
||||
seen, level, is_key=True)
|
||||
if valid_key:
|
||||
if not allow_duplicate_keys:
|
||||
if key_str in new_keys:
|
||||
raise ValueError('duplicate key %s' % repr(key))
|
||||
else:
|
||||
new_keys.add(key_str)
|
||||
if num_items_added:
|
||||
s += item_sep
|
||||
s += key_str + kv_sep + _dumps(obj[key], skipkeys, ensure_ascii,
|
||||
check_circular, allow_nan, indent,
|
||||
separators, default, sort_keys,
|
||||
quote_keys, trailing_commas,
|
||||
allow_duplicate_keys,
|
||||
seen, level, is_key=False)[1]
|
||||
num_items_added += 1
|
||||
elif not skipkeys:
|
||||
raise TypeError('invalid key %s' % repr(key))
|
||||
|
||||
s += end_str + u'}'
|
||||
return s
|
||||
|
||||
|
||||
def _dump_array(obj, skipkeys, ensure_ascii, check_circular, allow_nan,
|
||||
indent, separators, default, sort_keys,
|
||||
quote_keys, trailing_commas, allow_duplicate_keys,
|
||||
seen, level, item_sep, indent_str, end_str):
|
||||
if not obj:
|
||||
return u'[]'
|
||||
return (u'[' + indent_str +
|
||||
item_sep.join([_dumps(el, skipkeys, ensure_ascii, check_circular,
|
||||
allow_nan, indent, separators, default,
|
||||
sort_keys, quote_keys, trailing_commas,
|
||||
allow_duplicate_keys,
|
||||
seen, level, False)[1] for el in obj]) +
|
||||
end_str + u']')
|
||||
|
||||
|
||||
def _dump_float(obj, allow_nan):
|
||||
if allow_nan:
|
||||
if math.isnan(obj):
|
||||
return 'NaN'
|
||||
if obj == float('inf'):
|
||||
return 'Infinity'
|
||||
if obj == float('-inf'):
|
||||
return '-Infinity'
|
||||
elif math.isnan(obj) or obj == float('inf') or obj == float('-inf'):
|
||||
raise ValueError('Out of range float values '
|
||||
'are not JSON compliant')
|
||||
return str(obj)
|
||||
|
||||
|
||||
def _dump_str(obj, ensure_ascii):
|
||||
ret = ['"']
|
||||
for ch in obj:
|
||||
if ch == '\\':
|
||||
ret.append('\\\\')
|
||||
elif ch == '"':
|
||||
ret.append('\\"')
|
||||
elif ch == u'\u2028':
|
||||
ret.append('\\u2028')
|
||||
elif ch == u'\u2029':
|
||||
ret.append('\\u2029')
|
||||
elif ch == '\n':
|
||||
ret.append('\\n')
|
||||
elif ch == '\r':
|
||||
ret.append('\\r')
|
||||
elif ch == '\b':
|
||||
ret.append('\\b')
|
||||
elif ch == '\f':
|
||||
ret.append('\\f')
|
||||
elif ch == '\t':
|
||||
ret.append('\\t')
|
||||
elif ch == '\v':
|
||||
ret.append('\\v')
|
||||
elif ch == '\0':
|
||||
ret.append('\\0')
|
||||
elif not ensure_ascii:
|
||||
ret.append(ch)
|
||||
else:
|
||||
o = ord(ch)
|
||||
if o >= 32 and o < 128:
|
||||
ret.append(ch)
|
||||
elif o < 65536:
|
||||
ret.append('\\u' + '%04x' % o)
|
||||
else:
|
||||
val = o - 0x10000
|
||||
high = 0xd800 + (val >> 10)
|
||||
low = 0xdc00 + (val & 0x3ff)
|
||||
ret.append('\\u%04x\\u%04x' % (high, low))
|
||||
return u''.join(ret) + '"'
|
||||
|
||||
|
||||
def _is_ident(k):
|
||||
k = str(k)
|
||||
if not k or not _is_id_start(k[0]) and k[0] not in (u'$', u'_'):
|
||||
return False
|
||||
for ch in k[1:]:
|
||||
if not _is_id_continue(ch) and ch not in (u'$', u'_'):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _is_id_start(ch):
|
||||
return unicodedata.category(ch) in (
|
||||
'Lu', 'Ll', 'Li', 'Lt', 'Lm', 'Lo', 'Nl')
|
||||
|
||||
|
||||
def _is_id_continue(ch):
|
||||
return unicodedata.category(ch) in (
|
||||
'Lu', 'Ll', 'Li', 'Lt', 'Lm', 'Lo', 'Nl', 'Nd', 'Mn', 'Mc', 'Pc')
|
||||
|
||||
|
||||
_reserved_word_re = None
|
||||
|
||||
|
||||
def _is_reserved_word(k):
|
||||
global _reserved_word_re
|
||||
|
||||
if _reserved_word_re is None:
|
||||
# List taken from section 7.6.1 of ECMA-262.
|
||||
_reserved_word_re = re.compile('(' + '|'.join([
|
||||
'break',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'const',
|
||||
'continue',
|
||||
'debugger',
|
||||
'default',
|
||||
'delete',
|
||||
'do',
|
||||
'else',
|
||||
'enum',
|
||||
'export',
|
||||
'extends',
|
||||
'false',
|
||||
'finally',
|
||||
'for',
|
||||
'function',
|
||||
'if',
|
||||
'import',
|
||||
'in',
|
||||
'instanceof',
|
||||
'new',
|
||||
'null',
|
||||
'return',
|
||||
'super',
|
||||
'switch',
|
||||
'this',
|
||||
'throw',
|
||||
'true',
|
||||
'try',
|
||||
'typeof',
|
||||
'var',
|
||||
'void',
|
||||
'while',
|
||||
'with',
|
||||
]) + ')$')
|
||||
return _reserved_word_re.match(k) is not None
|
||||
|
||||
|
||||
def _raise_type_error(obj):
|
||||
raise TypeError('%s is not JSON5 serializable' % repr(obj))
|
@ -1,894 +0,0 @@
|
||||
# pylint: disable=line-too-long,unnecessary-lambda
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
# pylint: disable=redefined-builtin,invalid-name
|
||||
chr = unichr
|
||||
range = xrange
|
||||
str = unicode
|
||||
|
||||
|
||||
class Parser(object):
|
||||
def __init__(self, msg, fname):
|
||||
self.msg = str(msg)
|
||||
self.end = len(self.msg)
|
||||
self.fname = fname
|
||||
self.val = None
|
||||
self.pos = 0
|
||||
self.failed = False
|
||||
self.errpos = 0
|
||||
self._scopes = []
|
||||
self._cache = {}
|
||||
|
||||
def parse(self):
|
||||
self._grammar_()
|
||||
if self.failed:
|
||||
return None, self._err_str(), self.errpos
|
||||
return self.val, None, self.pos
|
||||
|
||||
def _err_str(self):
|
||||
lineno, colno = self._err_offsets()
|
||||
if self.errpos == len(self.msg):
|
||||
thing = 'end of input'
|
||||
else:
|
||||
thing = '"%s"' % self.msg[self.errpos]
|
||||
return '%s:%d Unexpected %s at column %d' % (
|
||||
self.fname, lineno, thing, colno)
|
||||
|
||||
def _err_offsets(self):
|
||||
lineno = 1
|
||||
colno = 1
|
||||
for i in range(self.errpos):
|
||||
if self.msg[i] == '\n':
|
||||
lineno += 1
|
||||
colno = 1
|
||||
else:
|
||||
colno += 1
|
||||
return lineno, colno
|
||||
|
||||
def _succeed(self, v, newpos=None):
|
||||
self.val = v
|
||||
self.failed = False
|
||||
if newpos is not None:
|
||||
self.pos = newpos
|
||||
|
||||
def _fail(self):
|
||||
self.val = None
|
||||
self.failed = True
|
||||
if self.pos >= self.errpos:
|
||||
self.errpos = self.pos
|
||||
|
||||
def _rewind(self, newpos):
|
||||
self._succeed(None, newpos)
|
||||
|
||||
def _bind(self, rule, var):
|
||||
rule()
|
||||
if not self.failed:
|
||||
self._set(var, self.val)
|
||||
|
||||
def _not(self, rule):
|
||||
p = self.pos
|
||||
rule()
|
||||
if self.failed:
|
||||
self._succeed(None, p)
|
||||
else:
|
||||
self._rewind(p)
|
||||
self._fail()
|
||||
|
||||
def _opt(self, rule):
|
||||
p = self.pos
|
||||
rule()
|
||||
if self.failed:
|
||||
self._succeed([], p)
|
||||
else:
|
||||
self._succeed([self.val])
|
||||
|
||||
def _plus(self, rule):
|
||||
vs = []
|
||||
rule()
|
||||
vs.append(self.val)
|
||||
if self.failed:
|
||||
return
|
||||
self._star(rule, vs)
|
||||
|
||||
def _star(self, rule, vs=None):
|
||||
vs = vs or []
|
||||
while not self.failed:
|
||||
p = self.pos
|
||||
rule()
|
||||
if self.failed:
|
||||
self._rewind(p)
|
||||
if p < self.errpos:
|
||||
self.errpos = p
|
||||
break
|
||||
else:
|
||||
vs.append(self.val)
|
||||
self._succeed(vs)
|
||||
|
||||
def _seq(self, rules):
|
||||
for rule in rules:
|
||||
rule()
|
||||
if self.failed:
|
||||
return
|
||||
|
||||
def _choose(self, rules):
|
||||
p = self.pos
|
||||
for rule in rules[:-1]:
|
||||
rule()
|
||||
if not self.failed:
|
||||
return
|
||||
self._rewind(p)
|
||||
rules[-1]()
|
||||
|
||||
def _ch(self, ch):
|
||||
p = self.pos
|
||||
if p < self.end and self.msg[p] == ch:
|
||||
self._succeed(ch, self.pos + 1)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _str(self, s):
|
||||
for ch in s:
|
||||
self._ch(ch)
|
||||
if self.failed:
|
||||
return
|
||||
self.val = s
|
||||
|
||||
def _range(self, i, j):
|
||||
p = self.pos
|
||||
if p != self.end and ord(i) <= ord(self.msg[p]) <= ord(j):
|
||||
self._succeed(self.msg[p], self.pos + 1)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _push(self, name):
|
||||
self._scopes.append((name, {}))
|
||||
|
||||
def _pop(self, name):
|
||||
actual_name, _ = self._scopes.pop()
|
||||
assert name == actual_name
|
||||
|
||||
def _get(self, var):
|
||||
return self._scopes[-1][1][var]
|
||||
|
||||
def _set(self, var, val):
|
||||
self._scopes[-1][1][var] = val
|
||||
|
||||
def _is_unicat(self, var, cat):
|
||||
import unicodedata
|
||||
return unicodedata.category(var) == cat
|
||||
|
||||
def _join(self, s, vs):
|
||||
return s.join(vs)
|
||||
|
||||
def _xtou(self, s):
|
||||
return chr(int(s, base=16))
|
||||
|
||||
def _grammar_(self):
|
||||
self._push('grammar')
|
||||
self._seq([self._sp_, lambda: self._bind(self._value_, 'v'), self._sp_,
|
||||
self._end_, lambda: self._succeed(self._get('v'))])
|
||||
self._pop('grammar')
|
||||
|
||||
def _sp_(self):
|
||||
self._star(self._ws_)
|
||||
|
||||
def _ws_(self):
|
||||
self._choose([self._ws__c0_, self._eol_, self._comment_, self._ws__c3_,
|
||||
self._ws__c4_, self._ws__c5_, self._ws__c6_,
|
||||
self._ws__c7_, self._ws__c8_])
|
||||
|
||||
def _ws__c0_(self):
|
||||
self._ch(' ')
|
||||
|
||||
def _ws__c3_(self):
|
||||
self._ch('\t')
|
||||
|
||||
def _ws__c4_(self):
|
||||
self._ch('\v')
|
||||
|
||||
def _ws__c5_(self):
|
||||
self._ch('\f')
|
||||
|
||||
def _ws__c6_(self):
|
||||
self._ch(u'\xa0')
|
||||
|
||||
def _ws__c7_(self):
|
||||
self._ch(u'\ufeff')
|
||||
|
||||
def _ws__c8_(self):
|
||||
self._push('ws__c8')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'), self._ws__c8__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('ws__c8')
|
||||
|
||||
def _ws__c8__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Zs')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _eol_(self):
|
||||
self._choose([self._eol__c0_, self._eol__c1_, self._eol__c2_,
|
||||
self._eol__c3_, self._eol__c4_])
|
||||
|
||||
def _eol__c0_(self):
|
||||
self._seq([lambda: self._ch('\r'), lambda: self._ch('\n')])
|
||||
|
||||
def _eol__c1_(self):
|
||||
self._ch('\r')
|
||||
|
||||
def _eol__c2_(self):
|
||||
self._ch('\n')
|
||||
|
||||
def _eol__c3_(self):
|
||||
self._ch(u'\u2028')
|
||||
|
||||
def _eol__c4_(self):
|
||||
self._ch(u'\u2029')
|
||||
|
||||
def _comment_(self):
|
||||
self._choose([self._comment__c0_, self._comment__c1_])
|
||||
|
||||
def _comment__c0_(self):
|
||||
self._seq([lambda: self._str('//'),
|
||||
lambda: self._star(self._comment__c0__s1_p_)])
|
||||
|
||||
def _comment__c0__s1_p_(self):
|
||||
self._seq([lambda: self._not(self._eol_), self._anything_])
|
||||
|
||||
def _comment__c1_(self):
|
||||
self._seq([lambda: self._str('/*'), self._comment__c1__s1_,
|
||||
lambda: self._str('*/')])
|
||||
|
||||
def _comment__c1__s1_(self):
|
||||
self._star(lambda: self._seq([self._comment__c1__s1_p__s0_, self._anything_]))
|
||||
|
||||
def _comment__c1__s1_p__s0_(self):
|
||||
self._not(lambda: self._str('*/'))
|
||||
|
||||
def _value_(self):
|
||||
self._choose([self._value__c0_, self._value__c1_, self._value__c2_,
|
||||
self._value__c3_, self._value__c4_, self._value__c5_,
|
||||
self._value__c6_])
|
||||
|
||||
def _value__c0_(self):
|
||||
self._seq([lambda: self._str('null'), lambda: self._succeed('None')])
|
||||
|
||||
def _value__c1_(self):
|
||||
self._seq([lambda: self._str('true'), lambda: self._succeed('True')])
|
||||
|
||||
def _value__c2_(self):
|
||||
self._seq([lambda: self._str('false'), lambda: self._succeed('False')])
|
||||
|
||||
def _value__c3_(self):
|
||||
self._push('value__c3')
|
||||
self._seq([lambda: self._bind(self._object_, 'v'),
|
||||
lambda: self._succeed(['object', self._get('v')])])
|
||||
self._pop('value__c3')
|
||||
|
||||
def _value__c4_(self):
|
||||
self._push('value__c4')
|
||||
self._seq([lambda: self._bind(self._array_, 'v'),
|
||||
lambda: self._succeed(['array', self._get('v')])])
|
||||
self._pop('value__c4')
|
||||
|
||||
def _value__c5_(self):
|
||||
self._push('value__c5')
|
||||
self._seq([lambda: self._bind(self._string_, 'v'),
|
||||
lambda: self._succeed(['string', self._get('v')])])
|
||||
self._pop('value__c5')
|
||||
|
||||
def _value__c6_(self):
|
||||
self._push('value__c6')
|
||||
self._seq([lambda: self._bind(self._num_literal_, 'v'),
|
||||
lambda: self._succeed(['number', self._get('v')])])
|
||||
self._pop('value__c6')
|
||||
|
||||
def _object_(self):
|
||||
self._choose([self._object__c0_, self._object__c1_])
|
||||
|
||||
def _object__c0_(self):
|
||||
self._push('object__c0')
|
||||
self._seq([lambda: self._ch('{'), self._sp_,
|
||||
lambda: self._bind(self._member_list_, 'v'), self._sp_,
|
||||
lambda: self._ch('}'), lambda: self._succeed(self._get('v'))])
|
||||
self._pop('object__c0')
|
||||
|
||||
def _object__c1_(self):
|
||||
self._seq([lambda: self._ch('{'), self._sp_, lambda: self._ch('}'),
|
||||
lambda: self._succeed([])])
|
||||
|
||||
def _array_(self):
|
||||
self._choose([self._array__c0_, self._array__c1_])
|
||||
|
||||
def _array__c0_(self):
|
||||
self._push('array__c0')
|
||||
self._seq([lambda: self._ch('['), self._sp_,
|
||||
lambda: self._bind(self._element_list_, 'v'), self._sp_,
|
||||
lambda: self._ch(']'), lambda: self._succeed(self._get('v'))])
|
||||
self._pop('array__c0')
|
||||
|
||||
def _array__c1_(self):
|
||||
self._seq([lambda: self._ch('['), self._sp_, lambda: self._ch(']'),
|
||||
lambda: self._succeed([])])
|
||||
|
||||
def _string_(self):
|
||||
self._choose([self._string__c0_, self._string__c1_])
|
||||
|
||||
def _string__c0_(self):
|
||||
self._push('string__c0')
|
||||
self._seq([self._squote_, self._string__c0__s1_, self._squote_,
|
||||
lambda: self._succeed(self._join('', self._get('cs')))])
|
||||
self._pop('string__c0')
|
||||
|
||||
def _string__c0__s1_(self):
|
||||
self._bind(lambda: self._star(self._sqchar_), 'cs')
|
||||
|
||||
def _string__c1_(self):
|
||||
self._push('string__c1')
|
||||
self._seq([self._dquote_, self._string__c1__s1_, self._dquote_,
|
||||
lambda: self._succeed(self._join('', self._get('cs')))])
|
||||
self._pop('string__c1')
|
||||
|
||||
def _string__c1__s1_(self):
|
||||
self._bind(lambda: self._star(self._dqchar_), 'cs')
|
||||
|
||||
def _sqchar_(self):
|
||||
self._choose([self._sqchar__c0_, self._sqchar__c1_, self._sqchar__c2_])
|
||||
|
||||
def _sqchar__c0_(self):
|
||||
self._push('sqchar__c0')
|
||||
self._seq([self._bslash_, lambda: self._bind(self._esc_char_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('sqchar__c0')
|
||||
|
||||
def _sqchar__c1_(self):
|
||||
self._seq([self._bslash_, self._eol_, lambda: self._succeed('')])
|
||||
|
||||
def _sqchar__c2_(self):
|
||||
self._push('sqchar__c2')
|
||||
self._seq([lambda: self._not(self._bslash_),
|
||||
lambda: self._not(self._squote_),
|
||||
lambda: self._not(self._eol_),
|
||||
lambda: self._bind(self._anything_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('sqchar__c2')
|
||||
|
||||
def _dqchar_(self):
|
||||
self._choose([self._dqchar__c0_, self._dqchar__c1_, self._dqchar__c2_])
|
||||
|
||||
def _dqchar__c0_(self):
|
||||
self._push('dqchar__c0')
|
||||
self._seq([self._bslash_, lambda: self._bind(self._esc_char_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('dqchar__c0')
|
||||
|
||||
def _dqchar__c1_(self):
|
||||
self._seq([self._bslash_, self._eol_, lambda: self._succeed('')])
|
||||
|
||||
def _dqchar__c2_(self):
|
||||
self._push('dqchar__c2')
|
||||
self._seq([lambda: self._not(self._bslash_),
|
||||
lambda: self._not(self._dquote_),
|
||||
lambda: self._not(self._eol_),
|
||||
lambda: self._bind(self._anything_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('dqchar__c2')
|
||||
|
||||
def _bslash_(self):
|
||||
self._ch('\\')
|
||||
|
||||
def _squote_(self):
|
||||
self._ch("'")
|
||||
|
||||
def _dquote_(self):
|
||||
self._ch('"')
|
||||
|
||||
def _esc_char_(self):
|
||||
self._choose([self._esc_char__c0_, self._esc_char__c1_,
|
||||
self._esc_char__c2_, self._esc_char__c3_,
|
||||
self._esc_char__c4_, self._esc_char__c5_,
|
||||
self._esc_char__c6_, self._esc_char__c7_,
|
||||
self._esc_char__c8_, self._esc_char__c9_,
|
||||
self._esc_char__c10_, self._esc_char__c11_,
|
||||
self._esc_char__c12_])
|
||||
|
||||
def _esc_char__c0_(self):
|
||||
self._seq([lambda: self._ch('b'), lambda: self._succeed('\b')])
|
||||
|
||||
def _esc_char__c1_(self):
|
||||
self._seq([lambda: self._ch('f'), lambda: self._succeed('\f')])
|
||||
|
||||
def _esc_char__c10_(self):
|
||||
self._seq([lambda: self._ch('0'), lambda: self._not(self._digit_),
|
||||
lambda: self._succeed('\x00')])
|
||||
|
||||
def _esc_char__c11_(self):
|
||||
self._push('esc_char__c11')
|
||||
self._seq([lambda: self._bind(self._hex_esc_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('esc_char__c11')
|
||||
|
||||
def _esc_char__c12_(self):
|
||||
self._push('esc_char__c12')
|
||||
self._seq([lambda: self._bind(self._unicode_esc_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('esc_char__c12')
|
||||
|
||||
def _esc_char__c2_(self):
|
||||
self._seq([lambda: self._ch('n'), lambda: self._succeed('\n')])
|
||||
|
||||
def _esc_char__c3_(self):
|
||||
self._seq([lambda: self._ch('r'), lambda: self._succeed('\r')])
|
||||
|
||||
def _esc_char__c4_(self):
|
||||
self._seq([lambda: self._ch('t'), lambda: self._succeed('\t')])
|
||||
|
||||
def _esc_char__c5_(self):
|
||||
self._seq([lambda: self._ch('v'), lambda: self._succeed('\v')])
|
||||
|
||||
def _esc_char__c6_(self):
|
||||
self._seq([self._squote_, lambda: self._succeed("'")])
|
||||
|
||||
def _esc_char__c7_(self):
|
||||
self._seq([self._dquote_, lambda: self._succeed('"')])
|
||||
|
||||
def _esc_char__c8_(self):
|
||||
self._seq([self._bslash_, lambda: self._succeed('\\')])
|
||||
|
||||
def _esc_char__c9_(self):
|
||||
self._push('esc_char__c9')
|
||||
self._seq([self._esc_char__c9__s0_,
|
||||
lambda: self._bind(self._anything_, 'c'),
|
||||
lambda: self._succeed(self._get('c'))])
|
||||
self._pop('esc_char__c9')
|
||||
|
||||
def _esc_char__c9__s0_(self):
|
||||
self._not(lambda: (self._esc_char__c9__s0_n_g_)())
|
||||
|
||||
def _esc_char__c9__s0_n_g_(self):
|
||||
self._choose([self._esc_char__c9__s0_n_g__c0_,
|
||||
self._esc_char__c9__s0_n_g__c1_,
|
||||
lambda: self._seq([self._digit_]),
|
||||
lambda: self._seq([self._eol_])])
|
||||
|
||||
def _esc_char__c9__s0_n_g__c0_(self):
|
||||
self._seq([lambda: self._ch('x')])
|
||||
|
||||
def _esc_char__c9__s0_n_g__c1_(self):
|
||||
self._seq([lambda: self._ch('u')])
|
||||
|
||||
def _hex_esc_(self):
|
||||
self._push('hex_esc')
|
||||
self._seq([lambda: self._ch('x'), lambda: self._bind(self._hex_, 'h1'),
|
||||
lambda: self._bind(self._hex_, 'h2'),
|
||||
lambda: self._succeed(self._xtou(self._get('h1') + self._get('h2')))])
|
||||
self._pop('hex_esc')
|
||||
|
||||
def _unicode_esc_(self):
|
||||
self._push('unicode_esc')
|
||||
self._seq([lambda: self._ch('u'), lambda: self._bind(self._hex_, 'a'),
|
||||
lambda: self._bind(self._hex_, 'b'),
|
||||
lambda: self._bind(self._hex_, 'c'),
|
||||
lambda: self._bind(self._hex_, 'd'),
|
||||
lambda: self._succeed(self._xtou(self._get('a') + self._get('b') + self._get('c') + self._get('d')))])
|
||||
self._pop('unicode_esc')
|
||||
|
||||
def _element_list_(self):
|
||||
self._push('element_list')
|
||||
self._seq([lambda: self._bind(self._value_, 'v'),
|
||||
self._element_list__s1_, self._sp_, self._element_list__s3_,
|
||||
lambda: self._succeed([self._get('v')] + self._get('vs'))])
|
||||
self._pop('element_list')
|
||||
|
||||
def _element_list__s1_(self):
|
||||
self._bind(lambda: self._star(self._element_list__s1_l_p_), 'vs')
|
||||
|
||||
def _element_list__s1_l_p_(self):
|
||||
self._seq([self._sp_, lambda: self._ch(','), self._sp_, self._value_])
|
||||
|
||||
def _element_list__s3_(self):
|
||||
self._opt(lambda: self._ch(','))
|
||||
|
||||
def _member_list_(self):
|
||||
self._push('member_list')
|
||||
self._seq([lambda: self._bind(self._member_, 'm'),
|
||||
self._member_list__s1_, self._sp_, self._member_list__s3_,
|
||||
lambda: self._succeed([self._get('m')] + self._get('ms'))])
|
||||
self._pop('member_list')
|
||||
|
||||
def _member_list__s1_(self):
|
||||
self._bind(lambda: self._star(self._member_list__s1_l_p_), 'ms')
|
||||
|
||||
def _member_list__s1_l_p_(self):
|
||||
self._seq([self._sp_, lambda: self._ch(','), self._sp_, self._member_])
|
||||
|
||||
def _member_list__s3_(self):
|
||||
self._opt(lambda: self._ch(','))
|
||||
|
||||
def _member_(self):
|
||||
self._choose([self._member__c0_, self._member__c1_])
|
||||
|
||||
def _member__c0_(self):
|
||||
self._push('member__c0')
|
||||
self._seq([lambda: self._bind(self._string_, 'k'), self._sp_,
|
||||
lambda: self._ch(':'), self._sp_,
|
||||
lambda: self._bind(self._value_, 'v'),
|
||||
lambda: self._succeed([self._get('k'), self._get('v')])])
|
||||
self._pop('member__c0')
|
||||
|
||||
def _member__c1_(self):
|
||||
self._push('member__c1')
|
||||
self._seq([lambda: self._bind(self._ident_, 'k'), self._sp_,
|
||||
lambda: self._ch(':'), self._sp_,
|
||||
lambda: self._bind(self._value_, 'v'),
|
||||
lambda: self._succeed([self._get('k'), self._get('v')])])
|
||||
self._pop('member__c1')
|
||||
|
||||
def _ident_(self):
|
||||
self._push('ident')
|
||||
self._seq([lambda: self._bind(self._id_start_, 'hd'), self._ident__s1_,
|
||||
lambda: self._succeed(self._join('', [self._get('hd')] + self._get('tl')))])
|
||||
self._pop('ident')
|
||||
|
||||
def _ident__s1_(self):
|
||||
self._bind(lambda: self._star(self._id_continue_), 'tl')
|
||||
|
||||
def _id_start_(self):
|
||||
self._choose([self._ascii_id_start_, self._other_id_start_,
|
||||
self._id_start__c2_])
|
||||
|
||||
def _id_start__c2_(self):
|
||||
self._seq([self._bslash_, self._unicode_esc_])
|
||||
|
||||
def _ascii_id_start_(self):
|
||||
self._choose([self._ascii_id_start__c0_, self._ascii_id_start__c1_,
|
||||
self._ascii_id_start__c2_, self._ascii_id_start__c3_])
|
||||
|
||||
def _ascii_id_start__c0_(self):
|
||||
self._range('a', 'z')
|
||||
|
||||
def _ascii_id_start__c1_(self):
|
||||
self._range('A', 'Z')
|
||||
|
||||
def _ascii_id_start__c2_(self):
|
||||
self._ch('$')
|
||||
|
||||
def _ascii_id_start__c3_(self):
|
||||
self._ch('_')
|
||||
|
||||
def _other_id_start_(self):
|
||||
self._choose([self._other_id_start__c0_, self._other_id_start__c1_,
|
||||
self._other_id_start__c2_, self._other_id_start__c3_,
|
||||
self._other_id_start__c4_, self._other_id_start__c5_])
|
||||
|
||||
def _other_id_start__c0_(self):
|
||||
self._push('other_id_start__c0')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c0__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c0')
|
||||
|
||||
def _other_id_start__c0__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Ll')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _other_id_start__c1_(self):
|
||||
self._push('other_id_start__c1')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c1__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c1')
|
||||
|
||||
def _other_id_start__c1__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Lm')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _other_id_start__c2_(self):
|
||||
self._push('other_id_start__c2')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c2__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c2')
|
||||
|
||||
def _other_id_start__c2__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Lo')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _other_id_start__c3_(self):
|
||||
self._push('other_id_start__c3')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c3__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c3')
|
||||
|
||||
def _other_id_start__c3__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Lt')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _other_id_start__c4_(self):
|
||||
self._push('other_id_start__c4')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c4__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c4')
|
||||
|
||||
def _other_id_start__c4__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Lu')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _other_id_start__c5_(self):
|
||||
self._push('other_id_start__c5')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._other_id_start__c5__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('other_id_start__c5')
|
||||
|
||||
def _other_id_start__c5__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Nl')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _id_continue_(self):
|
||||
self._choose([self._ascii_id_start_, self._digit_,
|
||||
self._other_id_start_, self._id_continue__c3_,
|
||||
self._id_continue__c4_, self._id_continue__c5_,
|
||||
self._id_continue__c6_, self._id_continue__c7_,
|
||||
self._id_continue__c8_, self._id_continue__c9_])
|
||||
|
||||
def _id_continue__c3_(self):
|
||||
self._push('id_continue__c3')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._id_continue__c3__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('id_continue__c3')
|
||||
|
||||
def _id_continue__c3__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Mn')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _id_continue__c4_(self):
|
||||
self._push('id_continue__c4')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._id_continue__c4__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('id_continue__c4')
|
||||
|
||||
def _id_continue__c4__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Mc')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _id_continue__c5_(self):
|
||||
self._push('id_continue__c5')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._id_continue__c5__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('id_continue__c5')
|
||||
|
||||
def _id_continue__c5__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Nd')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _id_continue__c6_(self):
|
||||
self._push('id_continue__c6')
|
||||
self._seq([lambda: self._bind(self._anything_, 'x'),
|
||||
self._id_continue__c6__s1_,
|
||||
lambda: self._succeed(self._get('x'))])
|
||||
self._pop('id_continue__c6')
|
||||
|
||||
def _id_continue__c6__s1_(self):
|
||||
v = self._is_unicat(self._get('x'), 'Pc')
|
||||
if v:
|
||||
self._succeed(v)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _id_continue__c7_(self):
|
||||
self._seq([self._bslash_, self._unicode_esc_])
|
||||
|
||||
def _id_continue__c8_(self):
|
||||
self._ch(u'\u200c')
|
||||
|
||||
def _id_continue__c9_(self):
|
||||
self._ch(u'\u200d')
|
||||
|
||||
def _num_literal_(self):
|
||||
self._choose([self._num_literal__c0_, self._num_literal__c1_,
|
||||
self._hex_literal_, self._num_literal__c3_,
|
||||
self._num_literal__c4_])
|
||||
|
||||
def _num_literal__c0_(self):
|
||||
self._push('num_literal__c0')
|
||||
self._seq([lambda: self._ch('-'),
|
||||
lambda: self._bind(self._num_literal_, 'n'),
|
||||
lambda: self._succeed('-' + self._get('n'))])
|
||||
self._pop('num_literal__c0')
|
||||
|
||||
def _num_literal__c1_(self):
|
||||
self._push('num_literal__c1')
|
||||
self._seq([self._num_literal__c1__s0_,
|
||||
lambda: self._bind(self._dec_literal_, 'd'),
|
||||
lambda: self._not(self._id_start_),
|
||||
lambda: self._succeed(self._get('d'))])
|
||||
self._pop('num_literal__c1')
|
||||
|
||||
def _num_literal__c1__s0_(self):
|
||||
self._opt(lambda: self._ch('+'))
|
||||
|
||||
def _num_literal__c3_(self):
|
||||
self._str('Infinity')
|
||||
|
||||
def _num_literal__c4_(self):
|
||||
self._str('NaN')
|
||||
|
||||
def _dec_literal_(self):
|
||||
self._choose([self._dec_literal__c0_, self._dec_literal__c1_,
|
||||
self._dec_literal__c2_, self._dec_literal__c3_,
|
||||
self._dec_literal__c4_, self._dec_literal__c5_])
|
||||
|
||||
def _dec_literal__c0_(self):
|
||||
self._push('dec_literal__c0')
|
||||
self._seq([lambda: self._bind(self._dec_int_lit_, 'd'),
|
||||
lambda: self._bind(self._frac_, 'f'),
|
||||
lambda: self._bind(self._exp_, 'e'),
|
||||
lambda: self._succeed(self._get('d') + self._get('f') + self._get('e'))])
|
||||
self._pop('dec_literal__c0')
|
||||
|
||||
def _dec_literal__c1_(self):
|
||||
self._push('dec_literal__c1')
|
||||
self._seq([lambda: self._bind(self._dec_int_lit_, 'd'),
|
||||
lambda: self._bind(self._frac_, 'f'),
|
||||
lambda: self._succeed(self._get('d') + self._get('f'))])
|
||||
self._pop('dec_literal__c1')
|
||||
|
||||
def _dec_literal__c2_(self):
|
||||
self._push('dec_literal__c2')
|
||||
self._seq([lambda: self._bind(self._dec_int_lit_, 'd'),
|
||||
lambda: self._bind(self._exp_, 'e'),
|
||||
lambda: self._succeed(self._get('d') + self._get('e'))])
|
||||
self._pop('dec_literal__c2')
|
||||
|
||||
def _dec_literal__c3_(self):
|
||||
self._push('dec_literal__c3')
|
||||
self._seq([lambda: self._bind(self._dec_int_lit_, 'd'),
|
||||
lambda: self._succeed(self._get('d'))])
|
||||
self._pop('dec_literal__c3')
|
||||
|
||||
def _dec_literal__c4_(self):
|
||||
self._push('dec_literal__c4')
|
||||
self._seq([lambda: self._bind(self._frac_, 'f'),
|
||||
lambda: self._bind(self._exp_, 'e'),
|
||||
lambda: self._succeed(self._get('f') + self._get('e'))])
|
||||
self._pop('dec_literal__c4')
|
||||
|
||||
def _dec_literal__c5_(self):
|
||||
self._push('dec_literal__c5')
|
||||
self._seq([lambda: self._bind(self._frac_, 'f'),
|
||||
lambda: self._succeed(self._get('f'))])
|
||||
self._pop('dec_literal__c5')
|
||||
|
||||
def _dec_int_lit_(self):
|
||||
self._choose([self._dec_int_lit__c0_, self._dec_int_lit__c1_])
|
||||
|
||||
def _dec_int_lit__c0_(self):
|
||||
self._seq([lambda: self._ch('0'), lambda: self._not(self._digit_),
|
||||
lambda: self._succeed('0')])
|
||||
|
||||
def _dec_int_lit__c1_(self):
|
||||
self._push('dec_int_lit__c1')
|
||||
self._seq([lambda: self._bind(self._nonzerodigit_, 'd'),
|
||||
self._dec_int_lit__c1__s1_,
|
||||
lambda: self._succeed(self._get('d') + self._join('', self._get('ds')))])
|
||||
self._pop('dec_int_lit__c1')
|
||||
|
||||
def _dec_int_lit__c1__s1_(self):
|
||||
self._bind(lambda: self._star(self._digit_), 'ds')
|
||||
|
||||
def _digit_(self):
|
||||
self._range('0', '9')
|
||||
|
||||
def _nonzerodigit_(self):
|
||||
self._range('1', '9')
|
||||
|
||||
def _hex_literal_(self):
|
||||
self._push('hex_literal')
|
||||
self._seq([self._hex_literal__s0_, self._hex_literal__s1_,
|
||||
lambda: self._succeed('0x' + self._join('', self._get('hs')))])
|
||||
self._pop('hex_literal')
|
||||
|
||||
def _hex_literal__s0_(self):
|
||||
self._choose([lambda: self._str('0x'), lambda: self._str('0X')])
|
||||
|
||||
def _hex_literal__s1_(self):
|
||||
self._bind(lambda: self._plus(self._hex_), 'hs')
|
||||
|
||||
def _hex_(self):
|
||||
self._choose([self._hex__c0_, self._hex__c1_, self._digit_])
|
||||
|
||||
def _hex__c0_(self):
|
||||
self._range('a', 'f')
|
||||
|
||||
def _hex__c1_(self):
|
||||
self._range('A', 'F')
|
||||
|
||||
def _frac_(self):
|
||||
self._push('frac')
|
||||
self._seq([lambda: self._ch('.'), self._frac__s1_,
|
||||
lambda: self._succeed('.' + self._join('', self._get('ds')))])
|
||||
self._pop('frac')
|
||||
|
||||
def _frac__s1_(self):
|
||||
self._bind(lambda: self._star(self._digit_), 'ds')
|
||||
|
||||
def _exp_(self):
|
||||
self._choose([self._exp__c0_, self._exp__c1_])
|
||||
|
||||
def _exp__c0_(self):
|
||||
self._push('exp__c0')
|
||||
self._seq([self._exp__c0__s0_,
|
||||
lambda: self._bind(self._exp__c0__s1_l_, 's'),
|
||||
self._exp__c0__s2_,
|
||||
lambda: self._succeed('e' + self._get('s') + self._join('', self._get('ds')))])
|
||||
self._pop('exp__c0')
|
||||
|
||||
def _exp__c0__s0_(self):
|
||||
self._choose([lambda: self._ch('e'), lambda: self._ch('E')])
|
||||
|
||||
def _exp__c0__s1_l_(self):
|
||||
self._choose([lambda: self._ch('+'), lambda: self._ch('-')])
|
||||
|
||||
def _exp__c0__s2_(self):
|
||||
self._bind(lambda: self._star(self._digit_), 'ds')
|
||||
|
||||
def _exp__c1_(self):
|
||||
self._push('exp__c1')
|
||||
self._seq([self._exp__c1__s0_, self._exp__c1__s1_,
|
||||
lambda: self._succeed('e' + self._join('', self._get('ds')))])
|
||||
self._pop('exp__c1')
|
||||
|
||||
def _exp__c1__s0_(self):
|
||||
self._choose([lambda: self._ch('e'), lambda: self._ch('E')])
|
||||
|
||||
def _exp__c1__s1_(self):
|
||||
self._bind(lambda: self._star(self._digit_), 'ds')
|
||||
|
||||
def _anything_(self):
|
||||
if self.pos < self.end:
|
||||
self._succeed(self.msg[self.pos], self.pos + 1)
|
||||
else:
|
||||
self._fail()
|
||||
|
||||
def _end_(self):
|
||||
if self.pos == self.end:
|
||||
self._succeed(None)
|
||||
else:
|
||||
self._fail()
|
@ -1,107 +0,0 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""A tool to parse and pretty-print JSON5.
|
||||
|
||||
Usage:
|
||||
|
||||
$ echo '{foo:"bar"}' | python -m json5.tool
|
||||
{
|
||||
foo: 'bar',
|
||||
}
|
||||
$ echo '{foo:"bar"}' | python -m json5.tool --as-json
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from . import arg_parser
|
||||
from . import lib
|
||||
from .host import Host
|
||||
from .version import VERSION
|
||||
|
||||
|
||||
def main(argv=None, host=None):
|
||||
host = host or Host()
|
||||
|
||||
parser = arg_parser.ArgumentParser(host, prog='json5', desc=__doc__)
|
||||
parser.add_argument('-c', metavar='STR', dest='cmd',
|
||||
help='inline json5 string to read instead of '
|
||||
'reading from a file')
|
||||
parser.add_argument('--as-json', dest='as_json', action='store_const',
|
||||
const=True, default=False,
|
||||
help='output as JSON '
|
||||
'(same as --quote-keys --no-trailing-commas)')
|
||||
parser.add_argument('--indent', dest='indent', default=4,
|
||||
help='amount to indent each line '
|
||||
'(default is 4 spaces)')
|
||||
parser.add_argument('--quote-keys', action='store_true', default=False,
|
||||
help='quote all object keys')
|
||||
parser.add_argument('--no-quote-keys', action='store_false',
|
||||
dest='quote_keys',
|
||||
help="don't quote object keys that are identifiers"
|
||||
" (this is the default)")
|
||||
parser.add_argument('--trailing-commas', action='store_true',
|
||||
default=True,
|
||||
help='add commas after the last item in multi-line '
|
||||
'objects and arrays (this is the default)')
|
||||
parser.add_argument('--no-trailing-commas', dest='trailing_commas',
|
||||
action='store_false',
|
||||
help='do not add commas after the last item in '
|
||||
'multi-line lists and objects')
|
||||
parser.add_argument('file', metavar='FILE', nargs='?', default='-',
|
||||
help='optional file to read JSON5 document from; if '
|
||||
'not specified or "-", will read from stdin '
|
||||
'instead')
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if parser.exit_status is not None:
|
||||
return parser.exit_status
|
||||
|
||||
if args.version:
|
||||
host.print_(VERSION)
|
||||
return 0
|
||||
|
||||
if args.cmd:
|
||||
inp = args.cmd
|
||||
elif args.file == '-':
|
||||
inp = host.stdin.read()
|
||||
else:
|
||||
inp = host.read_text_file(args.file)
|
||||
|
||||
if args.indent == 'None':
|
||||
args.indent = None
|
||||
else:
|
||||
try:
|
||||
args.indent = int(args.indent)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if args.as_json:
|
||||
args.quote_keys = True
|
||||
args.trailing_commas = False
|
||||
|
||||
obj = lib.loads(inp)
|
||||
s = lib.dumps(obj,
|
||||
indent=args.indent,
|
||||
quote_keys=args.quote_keys,
|
||||
trailing_commas=args.trailing_commas)
|
||||
host.print_(s)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__': # pragma: no cover
|
||||
sys.exit(main())
|
@ -1,15 +0,0 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
VERSION = '0.9.6'
|
20
libs/msdnicrosoft_logger/test/ctypes_print.py
Normal file
20
libs/msdnicrosoft_logger/test/ctypes_print.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -------------------------------
|
||||
# Difficult Rocket
|
||||
# Copyright © 2021-2022 by shenjackyuanjie
|
||||
# All rights reserved
|
||||
# -------------------------------
|
||||
|
||||
import time
|
||||
import ctypes
|
||||
|
||||
|
||||
def run_print():
|
||||
# 加载dll
|
||||
# ctypes.cdll.LoadLibrary('stdio')
|
||||
c_print = ctypes.cdll.LoadLibrary('./print.dll')
|
||||
c_print.print_it(ctypes.c_wchar_p(u'12啊3'), ctypes.c_wchar_p('\n'))
|
||||
c_print.print_it(ctypes.c_wchar_p(u'12啊3'), ctypes.c_wchar_p('\n'))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_print()
|
13
libs/msdnicrosoft_logger/test/print.c
Normal file
13
libs/msdnicrosoft_logger/test/print.c
Normal file
@ -0,0 +1,13 @@
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Python.h>
|
||||
|
||||
void print_it(wchar_t* out, wchar_t* end){
|
||||
printf("%s%s", out, end);
|
||||
};
|
||||
|
||||
static PyObject *print_it_py(PyObject *self, PyObject *args){
|
||||
PyObject *back_obj = PyObject_Str(PyObject);
|
||||
return back_obj;
|
||||
};
|
BIN
libs/msdnicrosoft_logger/test/print.dll
Normal file
BIN
libs/msdnicrosoft_logger/test/print.dll
Normal file
Binary file not shown.
@ -149,6 +149,7 @@ options = {
|
||||
'debug_trace_depth': 1,
|
||||
'debug_trace_flush': True,
|
||||
'debug_win32': False,
|
||||
'debug_input': False,
|
||||
'debug_x11': False,
|
||||
'shadow_window': True,
|
||||
'vsync': None,
|
||||
@ -178,6 +179,7 @@ _option_types = {
|
||||
'debug_trace_depth': int,
|
||||
'debug_trace_flush': bool,
|
||||
'debug_win32': bool,
|
||||
'debug_input': bool,
|
||||
'debug_x11': bool,
|
||||
'shadow_window': bool,
|
||||
'vsync': bool,
|
||||
|
@ -245,7 +245,7 @@ class EventLoop(event.EventDispatcher):
|
||||
self.clock.call_scheduled_functions(dt)
|
||||
|
||||
# Update timout
|
||||
return self.clock.get_sleep_time(True)
|
||||
return self.clock.get_sleep_time(False)
|
||||
|
||||
@property
|
||||
def has_exit(self):
|
||||
|
@ -38,19 +38,19 @@
|
||||
Measuring time
|
||||
==============
|
||||
|
||||
The `tick` and `get_fps` functions can be used in conjunction to fulfil most
|
||||
The `tick` and `get_frequency` functions can be used in conjunction to fulfil most
|
||||
games' basic requirements::
|
||||
|
||||
from pyglet import clock
|
||||
while True:
|
||||
dt = clock.tick()
|
||||
# ... update and render ...
|
||||
print(f"FPS is {clock.get_fps()}")
|
||||
print(f"FPS is {clock.get_frequency()}")
|
||||
|
||||
The ``dt`` value returned gives the number of seconds (as a float) since the
|
||||
last "tick".
|
||||
|
||||
The `get_fps` function averages the framerate over a sliding window of
|
||||
The `get_frequency` function averages the framerate over a sliding window of
|
||||
approximately 1 second. (You can calculate the instantaneous framerate by
|
||||
taking the reciprocal of ``dt``).
|
||||
|
||||
@ -176,7 +176,7 @@ class Clock:
|
||||
self.next_ts = self.time()
|
||||
self.last_ts = None
|
||||
|
||||
# Used by self.get_fps to show update frequency
|
||||
# Used by self.get_frequency to show update frequency
|
||||
self.times = _deque()
|
||||
self.cumulative_time = 0
|
||||
self.window_size = 60
|
||||
|
@ -1079,7 +1079,7 @@ class TabletCanvas(EventDispatcher):
|
||||
:event:
|
||||
"""
|
||||
|
||||
def on_motion(self, cursor, x, y, pressure, tilt_x, tilt_y):
|
||||
def on_motion(self, cursor, x, y, pressure, tilt_x, tilt_y, buttons):
|
||||
"""The cursor moved on the tablet surface.
|
||||
|
||||
If `pressure` is 0, then the cursor is actually hovering above the
|
||||
@ -1099,6 +1099,9 @@ class TabletCanvas(EventDispatcher):
|
||||
Currently undefined.
|
||||
`tilt_y` : float
|
||||
Currently undefined.
|
||||
`buttons` : int
|
||||
Button state may be provided if the platform supports it.
|
||||
Supported on: Windows
|
||||
|
||||
:event:
|
||||
"""
|
||||
|
@ -553,7 +553,8 @@ class EvdevControllerManager(ControllerManager, XlibSelectDevice):
|
||||
self._controllers[name] = controller
|
||||
|
||||
if controller:
|
||||
self.dispatch_event('on_connect', controller)
|
||||
# Dispatch event in main thread:
|
||||
pyglet.app.platform_event_loop.post_event(self, 'on_connect', controller)
|
||||
|
||||
def _make_device(self, name, count=1):
|
||||
path = os.path.join('/dev/input', name)
|
||||
|
@ -34,12 +34,14 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
import ctypes
|
||||
|
||||
from collections import defaultdict
|
||||
import pyglet
|
||||
from pyglet.input.base import DeviceOpenException
|
||||
from pyglet.input.base import Tablet, TabletCanvas
|
||||
|
||||
from pyglet.libs.win32 import libwintab as wintab
|
||||
from pyglet.util import debug_print
|
||||
|
||||
_debug = debug_print('debug_input')
|
||||
|
||||
lib = wintab.lib
|
||||
|
||||
@ -116,12 +118,19 @@ class WintabTablet(Tablet):
|
||||
|
||||
|
||||
class WintabTabletCanvas(TabletCanvas):
|
||||
override_keys = False
|
||||
|
||||
def __init__(self, device, window, msg_base=wintab.WT_DEFBASE):
|
||||
super(WintabTabletCanvas, self).__init__(window)
|
||||
|
||||
self.device = device
|
||||
self.msg_base = msg_base
|
||||
|
||||
# Get the extension masks available. Only need to do this once.
|
||||
global _extension_masks
|
||||
if not _extension_masks:
|
||||
_extension_masks = get_extension_masks()
|
||||
|
||||
# Just use system context, for similarity w/ os x and xinput.
|
||||
# WTI_DEFCONTEXT detaches mouse from tablet, which is nice, but not
|
||||
# possible on os x afiak.
|
||||
@ -132,11 +141,11 @@ class WintabTabletCanvas(TabletCanvas):
|
||||
|
||||
# If you change this, change definition of PACKET also.
|
||||
context_info.lcPktData = (
|
||||
wintab.PK_CHANGED | wintab.PK_CURSOR | wintab.PK_BUTTONS |
|
||||
wintab.PK_X | wintab.PK_Y | wintab.PK_Z |
|
||||
wintab.PK_NORMAL_PRESSURE | wintab.PK_TANGENT_PRESSURE |
|
||||
wintab.PK_ORIENTATION)
|
||||
context_info.lcPktMode = 0 # All absolute
|
||||
wintab.PK_CHANGED | wintab.PK_CURSOR | wintab.PK_BUTTONS |
|
||||
wintab.PK_X | wintab.PK_Y | wintab.PK_Z |
|
||||
wintab.PK_NORMAL_PRESSURE | wintab.PK_TANGENT_PRESSURE |
|
||||
wintab.PK_ORIENTATION) | _extension_masks
|
||||
context_info.lcPktMode = 0 # All absolute (PACKETMODE)
|
||||
|
||||
self._context = lib.WTOpenW(window._hwnd, ctypes.byref(context_info), True)
|
||||
if not self._context:
|
||||
@ -145,10 +154,66 @@ class WintabTabletCanvas(TabletCanvas):
|
||||
window._event_handlers[msg_base + wintab.WT_PACKET] = self._event_wt_packet
|
||||
window._event_handlers[msg_base + wintab.WT_PROXIMITY] = self._event_wt_proximity
|
||||
|
||||
if _extension_masks:
|
||||
window._event_handlers[msg_base + wintab.WT_PACKETEXT] = self._event_wt_packetext
|
||||
|
||||
self._current_cursor = None
|
||||
self._pressure_scale = device.pressure_axis.get_scale()
|
||||
self._pressure_bias = device.pressure_axis.get_bias()
|
||||
|
||||
self.express_keys = defaultdict(lambda: defaultdict(bool)) # [control_id][location_id]
|
||||
self.express_key_ct = 0
|
||||
self.touchrings = [] # Not currently implemented.
|
||||
self.touchstrips = [] # Not currently implemented.
|
||||
|
||||
# Override test
|
||||
for tablet_id in range(get_tablet_count()):
|
||||
control_count = self.extension_get(wintab.WTX_EXPKEYS2, tablet_id, 0, 0,
|
||||
wintab.TABLET_PROPERTY_CONTROLCOUNT)
|
||||
self.express_key_ct = control_count
|
||||
assert _debug(f"Controls Found: {control_count}")
|
||||
if self.override_keys is True:
|
||||
for control_id in range(control_count):
|
||||
function_count = self.extension_get(wintab.WTX_EXPKEYS2, tablet_id, control_id, 0,
|
||||
wintab.TABLET_PROPERTY_FUNCCOUNT)
|
||||
for function_id in range(function_count):
|
||||
self.extension_set(wintab.WTX_EXPKEYS2, tablet_id, control_id, function_id,
|
||||
wintab.TABLET_PROPERTY_OVERRIDE, wintab.BOOL(True))
|
||||
|
||||
def extension_get(self, extension, tablet_id, control_id, function_id, property_id, value_type=wintab.UINT):
|
||||
prop = wintab.EXTPROPERTY()
|
||||
|
||||
prop.version = 0
|
||||
prop.tabletIndex = tablet_id
|
||||
prop.controlIndex = control_id
|
||||
prop.functionIndex = function_id
|
||||
prop.propertyID = property_id
|
||||
prop.reserved = 0
|
||||
prop.dataSize = ctypes.sizeof(value_type)
|
||||
|
||||
success = lib.WTExtGet(self._context, extension, ctypes.byref(prop))
|
||||
if success:
|
||||
return ctypes.cast(prop.data, ctypes.POINTER(value_type)).contents.value
|
||||
|
||||
return 0
|
||||
|
||||
def extension_set(self, extension, tablet_id, control_id, function_id, property_id, value):
|
||||
prop = wintab.EXTPROPERTY()
|
||||
prop.version = 0
|
||||
prop.tabletIndex = tablet_id
|
||||
prop.controlIndex = control_id
|
||||
prop.functionIndex = function_id
|
||||
prop.propertyID = property_id
|
||||
prop.reserved = 0
|
||||
prop.dataSize = ctypes.sizeof(value)
|
||||
prop.data[0] = value.value
|
||||
|
||||
success = lib.WTExtSet(self._context, extension, ctypes.byref(prop))
|
||||
if success:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
lib.WTClose(self._context)
|
||||
self._context = None
|
||||
@ -156,6 +221,9 @@ class WintabTabletCanvas(TabletCanvas):
|
||||
del self.window._event_handlers[self.msg_base + wintab.WT_PACKET]
|
||||
del self.window._event_handlers[self.msg_base + wintab.WT_PROXIMITY]
|
||||
|
||||
if _extension_masks:
|
||||
del self.window._event_handlers[self.msg_base + wintab.WT_PACKETEXT]
|
||||
|
||||
def _set_current_cursor(self, cursor_type):
|
||||
if self._current_cursor:
|
||||
self.dispatch_event('on_leave', self._current_cursor)
|
||||
@ -186,7 +254,25 @@ class WintabTabletCanvas(TabletCanvas):
|
||||
if self._current_cursor is None:
|
||||
self._set_current_cursor(packet.pkCursor)
|
||||
|
||||
self.dispatch_event('on_motion', self._current_cursor, x, y, pressure, 0., 0.)
|
||||
self.dispatch_event('on_motion', self._current_cursor, x, y, pressure, 0., 0., packet.pkButtons)
|
||||
|
||||
@pyglet.window.win32.Win32EventHandler(0)
|
||||
def _event_wt_packetext(self, msg, wParam, lParam):
|
||||
packet = wintab.PACKETEXT()
|
||||
if lib.WTPacket(lParam, wParam, ctypes.byref(packet)) == 0:
|
||||
return
|
||||
|
||||
# Proper context exists in the packet, not the lParam.
|
||||
if packet.pkBase.nContext == self._context:
|
||||
if packet.pkExpKeys.nControl < self.express_key_ct:
|
||||
current_state = self.express_keys[packet.pkExpKeys.nControl][packet.pkExpKeys.nLocation]
|
||||
new_state = bool(packet.pkExpKeys.nState)
|
||||
if current_state != new_state:
|
||||
event_type = "on_express_key_press" if new_state else "on_express_key_release"
|
||||
|
||||
self.express_keys[packet.pkExpKeys.nControl][packet.pkExpKeys.nLocation] = new_state
|
||||
|
||||
self.dispatch_event(event_type, packet.pkExpKeys.nControl, packet.pkExpKeys.nLocation)
|
||||
|
||||
@pyglet.window.win32.Win32EventHandler(0)
|
||||
def _event_wt_proximity(self, msg, wParam, lParam):
|
||||
@ -205,6 +291,40 @@ class WintabTabletCanvas(TabletCanvas):
|
||||
# can actually grab a cursor id.
|
||||
self._current_cursor = None
|
||||
|
||||
def on_express_key_press(self, control_id: int, location_id: int):
|
||||
"""An event called when an ExpressKey is pressed down.
|
||||
|
||||
:Parameters:
|
||||
`control_id` : int
|
||||
Zero-based index number given to the assigned key by the driver.
|
||||
The same control_id may exist in multiple locations, which the location_id is used to differentiate.
|
||||
`location_id: int
|
||||
Zero-based index indicating side of tablet where control id was found.
|
||||
Some tablets may have clusters of ExpressKey's on various areas of the tablet.
|
||||
(0 = left, 1 = right, 2 = top, 3 = bottom, 4 = transducer).
|
||||
|
||||
:event:
|
||||
"""
|
||||
|
||||
def on_express_key_release(self, control_id: int, location_id: int):
|
||||
"""An event called when an ExpressKey is released.
|
||||
|
||||
:Parameters:
|
||||
`control_id` : int
|
||||
Zero-based index number given to the assigned key by the driver.
|
||||
The same control_id may exist in multiple locations, which the location_id is used to differentiate.
|
||||
`location_id: int
|
||||
Zero-based index indicating side of tablet where control id was found.
|
||||
Some tablets may have clusters of ExpressKey's on various areas of the tablet.
|
||||
(0 = left, 1 = right, 2 = top, 3 = bottom, 4 = transducer).
|
||||
|
||||
:event:
|
||||
"""
|
||||
|
||||
|
||||
WintabTabletCanvas.register_event_type('on_express_key_press')
|
||||
WintabTabletCanvas.register_event_type('on_express_key_release')
|
||||
|
||||
|
||||
class WintabTabletCursor:
|
||||
def __init__(self, device, index):
|
||||
@ -244,11 +364,73 @@ def get_implementation_version():
|
||||
return impl_version
|
||||
|
||||
|
||||
def get_tablets(display=None):
|
||||
# Require spec version 1.1 or greater
|
||||
if get_spec_version() < 0x101:
|
||||
return []
|
||||
def extension_index(ext):
|
||||
"""Check if a particular extension exists within the driver."""
|
||||
exists = True
|
||||
i = 0
|
||||
index = 0xFFFFFFFF
|
||||
|
||||
while exists:
|
||||
tag = wintab.UINT()
|
||||
exists = lib.WTInfoW(wintab.WTI_EXTENSIONS + i, wintab.EXT_TAG, ctypes.byref(tag))
|
||||
if tag.value == ext:
|
||||
index = i
|
||||
break
|
||||
|
||||
i += 1
|
||||
|
||||
if index != 0xFFFFFFFF:
|
||||
return index
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_extension_masks():
|
||||
"""Determine which extension support is available by getting the masks."""
|
||||
masks = 0
|
||||
tr_idx = extension_index(wintab.WTX_TOUCHRING)
|
||||
if tr_idx is not None:
|
||||
assert _debug("Touchring support found")
|
||||
masks |= wtinfo_uint(wintab.WTI_EXTENSIONS + tr_idx, wintab.EXT_MASK)
|
||||
else:
|
||||
assert _debug("Touchring extension not found.")
|
||||
|
||||
ts_idx = extension_index(wintab.WTX_TOUCHSTRIP)
|
||||
if ts_idx is not None:
|
||||
assert _debug("Touchstrip support found.")
|
||||
masks |= wtinfo_uint(wintab.WTI_EXTENSIONS + ts_idx, wintab.EXT_MASK)
|
||||
else:
|
||||
assert _debug("Touchstrip extension not found.")
|
||||
|
||||
expkeys_idx = extension_index(wintab.WTX_EXPKEYS2)
|
||||
if expkeys_idx is not None:
|
||||
assert _debug("ExpressKey support found.")
|
||||
masks |= wtinfo_uint(wintab.WTI_EXTENSIONS + expkeys_idx, wintab.EXT_MASK)
|
||||
else:
|
||||
assert _debug("ExpressKey extension not found.")
|
||||
|
||||
return masks
|
||||
|
||||
|
||||
def get_tablet_count():
|
||||
"""Return just the number of current devices."""
|
||||
spec_version = get_spec_version()
|
||||
assert _debug(f"Wintab Version: {spec_version}")
|
||||
if spec_version < 0x101:
|
||||
return 0
|
||||
|
||||
n_devices = wtinfo_uint(wintab.WTI_INTERFACE, wintab.IFC_NDEVICES)
|
||||
return n_devices
|
||||
|
||||
|
||||
_extension_masks = None
|
||||
|
||||
|
||||
def get_tablets(display=None):
|
||||
# Require spec version 1.1 or greater
|
||||
n_devices = get_tablet_count()
|
||||
if not n_devices:
|
||||
return []
|
||||
|
||||
devices = [WintabTablet(i) for i in range(n_devices)]
|
||||
return devices
|
||||
|
@ -93,7 +93,7 @@ class XInputTabletCanvas(DeviceResponder, TabletCanvas):
|
||||
x = e.x
|
||||
y = self.window.height - e.y
|
||||
pressure = e.axis_data[2] / float(cursor.max_pressure)
|
||||
self.dispatch_event('on_motion', cursor, x, y, pressure, 0.0, 0.0)
|
||||
self.dispatch_event('on_motion', cursor, x, y, pressure, 0.0, 0.0, 0.0)
|
||||
|
||||
def _proximity_in(self, e):
|
||||
cursor = self._cursor_map.get(e.deviceid)
|
||||
|
@ -436,6 +436,7 @@ class XInputDeviceManager(EventDispatcher):
|
||||
with self._dev_lock:
|
||||
return [dev for dev in self.all_devices if dev.connected]
|
||||
|
||||
# Threaded method:
|
||||
def _get_state(self):
|
||||
xuser_max_count = set(range(XUSER_MAX_COUNT)) # {0, 1, 2, 3}
|
||||
polling_rate = self._polling_rate
|
||||
@ -457,7 +458,8 @@ class XInputDeviceManager(EventDispatcher):
|
||||
# Found a new connection:
|
||||
device.connected = True
|
||||
self._connected_devices.add(i)
|
||||
self.dispatch_event('on_connect', device)
|
||||
# Dispatch event in main thread:
|
||||
pyglet.app.platform_event_loop.post_event(self, 'on_connect', device)
|
||||
|
||||
elapsed = 0.0
|
||||
|
||||
@ -472,7 +474,8 @@ class XInputDeviceManager(EventDispatcher):
|
||||
if device.connected:
|
||||
device.connected = False
|
||||
self._connected_devices.remove(i)
|
||||
self.dispatch_event('on_disconnect', device)
|
||||
# Dispatch event in main thread:
|
||||
pyglet.app.platform_event_loop.post_event(self, 'on_disconnect', device)
|
||||
continue
|
||||
|
||||
elif result == ERROR_SUCCESS and device.is_open:
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
import atexit
|
||||
import struct
|
||||
import warnings
|
||||
|
||||
import pyglet
|
||||
from . import com
|
||||
|
@ -34,17 +34,13 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
import ctypes
|
||||
from ctypes.wintypes import HANDLE, BYTE, HWND, BOOL, UINT, LONG, WORD, DWORD, WCHAR, LPVOID
|
||||
|
||||
lib = ctypes.windll.wintab32
|
||||
|
||||
LONG = ctypes.c_long
|
||||
BOOL = ctypes.c_int
|
||||
UINT = ctypes.c_uint
|
||||
WORD = ctypes.c_uint16
|
||||
DWORD = ctypes.c_uint32
|
||||
WCHAR = ctypes.c_wchar
|
||||
FIX32 = DWORD
|
||||
WTPKT = DWORD
|
||||
HCTX = HANDLE # CONTEXT HANDLE
|
||||
|
||||
LCNAMELEN = 40
|
||||
|
||||
@ -119,6 +115,56 @@ class LOGCONTEXT(ctypes.Structure):
|
||||
)
|
||||
|
||||
|
||||
class TILT(ctypes.Structure): # 1.1
|
||||
_fields_ = (
|
||||
('tiltX', ctypes.c_int),
|
||||
('tiltY', ctypes.c_int),
|
||||
)
|
||||
|
||||
|
||||
class EXTENSIONBASE(ctypes.Structure): # 1.4
|
||||
_fields_ = (
|
||||
('nContext', HCTX), # Specifies the Wintab context to which these properties apply.
|
||||
('nStatus', UINT), # Status of setting/getting properties.
|
||||
('nTime', DWORD), # Timestamp applied to property transaction.
|
||||
('nSerialNumber', UINT), # Reserved - not use
|
||||
)
|
||||
|
||||
|
||||
class EXPKEYSDATA(ctypes.Structure): # 1.4
|
||||
_fields_ = (
|
||||
('nTablet', BYTE), # Tablet index where control is found.
|
||||
('nControl', BYTE), # Zero-based control index.
|
||||
('nLocation', BYTE), # Zero-based index indicating side of tablet where control found (0 = left, 1 = right).
|
||||
('nReserved', BYTE), # Reserved - not used
|
||||
('nState', DWORD) # Indicates Express Key button press (1 = pressed, 0 = released)
|
||||
)
|
||||
|
||||
|
||||
class SLIDERDATA(ctypes.Structure): # 1.4
|
||||
_fields_ = (
|
||||
('nTablet', BYTE), # Tablet index where control is found.
|
||||
('nControl', BYTE), # Zero-based control index.
|
||||
('nMode', BYTE), # Zero-based current active mode of control. Mode selected by control's toggle button.
|
||||
('nReserved', BYTE), # Reserved - not used
|
||||
('nPosition', DWORD) # An integer representing the position of the user's finger on the control.
|
||||
# When there is no finger on the control, this value is negative.
|
||||
)
|
||||
|
||||
|
||||
class EXTPROPERTY(ctypes.Structure): # 1.4
|
||||
_fields_ = (
|
||||
('version', BYTE), # Structure version, 0 for now
|
||||
('tabletIndex', BYTE), # 0-based index for tablet
|
||||
('controlIndex', BYTE), # 0-based index for control
|
||||
('functionIndex', BYTE), # 0-based index for control's sub-function
|
||||
('propertyID', WORD), # property ID
|
||||
('reserved', WORD), # DWORD-alignment filler
|
||||
('dataSize', DWORD), # number of bytes in data[] buffer
|
||||
('data', BYTE * 1), # raw data
|
||||
)
|
||||
|
||||
|
||||
# Custom packet format with fields
|
||||
# PK_CHANGED
|
||||
# PK_CURSOR
|
||||
@ -143,6 +189,15 @@ class PACKET(ctypes.Structure):
|
||||
)
|
||||
|
||||
|
||||
class PACKETEXT(ctypes.Structure):
|
||||
_fields_ = (
|
||||
('pkBase', EXTENSIONBASE), # Extension control properties common to all control types.
|
||||
('pkExpKeys', EXPKEYSDATA), # Extension data for one Express Key.
|
||||
('pkTouchStrip', SLIDERDATA), # Extension data for one Touch Strip.
|
||||
('pkTouchRing', SLIDERDATA) # Extension data for one Touch Ring.
|
||||
)
|
||||
|
||||
|
||||
PK_CONTEXT = 0x0001 # reporting context
|
||||
PK_STATUS = 0x0002 # status bits
|
||||
PK_TIME = 0x0004 # time stamp
|
||||
@ -174,6 +229,7 @@ WT_CTXOVERLAP = 4
|
||||
WT_PROXIMITY = 5
|
||||
WT_INFOCHANGE = 6
|
||||
WT_CSRCHANGE = 7
|
||||
WT_PACKETEXT = 8
|
||||
|
||||
# system button assignment values
|
||||
SBN_NONE = 0x00
|
||||
@ -370,4 +426,47 @@ WTX_FKEYS = 1 # Function keys
|
||||
WTX_TILT = 2 # Raw Cartesian tilt; 1.1
|
||||
WTX_CSRMASK = 3 # select input by cursor type; 1.1
|
||||
WTX_XBTNMASK = 4 # Extended button mask; 1.1
|
||||
WTX_EXPKEYS = 5 # ExpressKeys; 1.3
|
||||
WTX_EXPKEYS = 5 # ExpressKeys; 1.3 - DEPRECATED USE 2
|
||||
WTX_TOUCHSTRIP = 6 # TouchStrips; 1.4
|
||||
WTX_TOUCHRING = 7 # TouchRings; 1.4
|
||||
WTX_EXPKEYS2 = 8 # ExpressKeys; 1.4
|
||||
|
||||
TABLET_PROPERTY_CONTROLCOUNT = 0 # UINT32: number of physical controls on tablet
|
||||
TABLET_PROPERTY_FUNCCOUNT = 1 # UINT32: number of functions of control
|
||||
TABLET_PROPERTY_AVAILABLE = 2 # BOOL: control/mode is available for override
|
||||
TABLET_PROPERTY_MIN = 3 # UINT32: minimum value
|
||||
TABLET_PROPERTY_MAX = 4 # UINT32: maximum value
|
||||
TABLET_PROPERTY_OVERRIDE = 5 # BOOL: control is overridden
|
||||
TABLET_PROPERTY_OVERRIDE_NAME = 6 # UTF-8: Displayable name when control is overridden
|
||||
TABLET_PROPERTY_OVERRIDE_ICON = 7 # Image: Icon to show when control is overridden
|
||||
TABLET_PROPERTY_ICON_WIDTH = 8 # UINT32: Pixel width of icon display
|
||||
TABLET_PROPERTY_ICON_HEIGHT = 9 # UINT32: Pixel height of icon display
|
||||
TABLET_PROPERTY_ICON_FORMAT = 10 # UINT32: UINT32: Pixel format of icon display (see TABLET_ICON_FMT_*)
|
||||
TABLET_PROPERTY_LOCATION = 11 # UINT32: Physical location of control (see TABLET_LOC_*)
|
||||
|
||||
TABLET_LOC_LEFT = 0
|
||||
TABLET_LOC_RIGHT = 1
|
||||
TABLET_LOC_TOP = 2
|
||||
TABLET_LOC_BOTTOM = 3
|
||||
TABLET_LOC_TRANSDUCER = 4
|
||||
|
||||
lib.WTOpenW.restype = HCTX
|
||||
lib.WTOpenW.argtypes = [HWND, ctypes.POINTER(LOGCONTEXT), BOOL]
|
||||
|
||||
lib.WTClose.restype = BOOL
|
||||
lib.WTClose.argtypes = [HCTX]
|
||||
|
||||
lib.WTInfoW.restype = UINT
|
||||
lib.WTInfoW.argtypes = [UINT, UINT, LPVOID]
|
||||
|
||||
lib.WTPacket.restype = BOOL
|
||||
lib.WTPacket.argtypes = [HCTX, UINT, LPVOID]
|
||||
|
||||
lib.WTGetW.restype = BOOL
|
||||
lib.WTGetW.argtypes = [HCTX, BOOL]
|
||||
|
||||
lib.WTExtGet.restype = BOOL
|
||||
lib.WTExtGet.argtypes = [HCTX, UINT, LPVOID]
|
||||
|
||||
lib.WTExtSet.restype = BOOL
|
||||
lib.WTExtSet.argtypes = [HCTX, UINT, LPVOID]
|
||||
|
@ -73,9 +73,11 @@ creating scrollable layouts.
|
||||
.. versionadded:: 1.1
|
||||
"""
|
||||
|
||||
import os.path
|
||||
from os.path import dirname as _dirname
|
||||
from os.path import splitext as _splitext
|
||||
|
||||
import pyglet
|
||||
|
||||
from pyglet.text import layout, document, caret
|
||||
|
||||
|
||||
@ -130,7 +132,7 @@ def get_decoder(filename, mimetype=None):
|
||||
:rtype: `DocumentDecoder`
|
||||
"""
|
||||
if mimetype is None:
|
||||
_, ext = os.path.splitext(filename)
|
||||
_, ext = _splitext(filename)
|
||||
if ext.lower() in ('.htm', '.html', '.xhtml'):
|
||||
mimetype = 'text/html'
|
||||
else:
|
||||
@ -176,7 +178,7 @@ def load(filename, file=None, mimetype=None):
|
||||
if hasattr(file_contents, "decode"):
|
||||
file_contents = file_contents.decode()
|
||||
|
||||
location = pyglet.resource.FileLocation(os.path.dirname(filename))
|
||||
location = pyglet.resource.FileLocation(_dirname(filename))
|
||||
return decoder.decode(file_contents, location)
|
||||
|
||||
|
||||
@ -265,11 +267,7 @@ class DocumentLabel(layout.TextLayout):
|
||||
Optional graphics group to use.
|
||||
|
||||
"""
|
||||
super(DocumentLabel, self).__init__(document,
|
||||
width=width, height=height,
|
||||
multiline=multiline,
|
||||
dpi=dpi, batch=batch, group=group)
|
||||
|
||||
super().__init__(document, width, height, multiline, dpi, batch, group)
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._anchor_x = anchor_x
|
||||
@ -347,8 +345,7 @@ class DocumentLabel(layout.TextLayout):
|
||||
|
||||
@font_size.setter
|
||||
def font_size(self, font_size):
|
||||
self.document.set_style(0, len(self.document.text),
|
||||
{'font_size': font_size})
|
||||
self.document.set_style(0, len(self.document.text), {'font_size': font_size})
|
||||
|
||||
@property
|
||||
def bold(self):
|
||||
@ -360,8 +357,7 @@ class DocumentLabel(layout.TextLayout):
|
||||
|
||||
@bold.setter
|
||||
def bold(self, bold):
|
||||
self.document.set_style(0, len(self.document.text),
|
||||
{'bold': bold})
|
||||
self.document.set_style(0, len(self.document.text), {'bold': bold})
|
||||
|
||||
@property
|
||||
def italic(self):
|
||||
@ -373,8 +369,7 @@ class DocumentLabel(layout.TextLayout):
|
||||
|
||||
@italic.setter
|
||||
def italic(self, italic):
|
||||
self.document.set_style(0, len(self.document.text),
|
||||
{'italic': italic})
|
||||
self.document.set_style(0, len(self.document.text), {'italic': italic})
|
||||
|
||||
def get_style(self, name):
|
||||
"""Get a document style value by name.
|
||||
@ -404,6 +399,9 @@ class DocumentLabel(layout.TextLayout):
|
||||
"""
|
||||
self.document.set_style(0, len(self.document.text), {name: value})
|
||||
|
||||
def __del__(self):
|
||||
self.delete()
|
||||
|
||||
|
||||
class Label(DocumentLabel):
|
||||
"""Plain text label.
|
||||
@ -463,10 +461,8 @@ class Label(DocumentLabel):
|
||||
Optional graphics group to use.
|
||||
|
||||
"""
|
||||
document = decode_text(text)
|
||||
super(Label, self).__init__(document, x, y, width, height,
|
||||
anchor_x, anchor_y,
|
||||
multiline, dpi, batch, group)
|
||||
doc = decode_text(text)
|
||||
super().__init__(doc, x, y, width, height, anchor_x, anchor_y, multiline, dpi, batch, group)
|
||||
|
||||
self.document.set_style(0, len(self.document.text), {
|
||||
'font_name': font_name,
|
||||
@ -525,10 +521,8 @@ class HTMLLabel(DocumentLabel):
|
||||
"""
|
||||
self._text = text
|
||||
self._location = location
|
||||
document = decode_html(text, location)
|
||||
super(HTMLLabel, self).__init__(document, x, y, width, height,
|
||||
anchor_x, anchor_y,
|
||||
multiline, dpi, batch, group)
|
||||
doc = decode_html(text, location)
|
||||
super().__init__(doc, x, y, width, height, anchor_x, anchor_y, multiline, dpi, batch, group)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
@ -542,4 +536,3 @@ class HTMLLabel(DocumentLabel):
|
||||
def text(self, text):
|
||||
self._text = text
|
||||
self.document = decode_html(text, self._location)
|
||||
|
||||
|
@ -1851,7 +1851,7 @@ class FPSDisplay:
|
||||
#: :type: float
|
||||
update_period = 0.25
|
||||
|
||||
def __init__(self, window, color=(127, 127, 127, 127), samples=60):
|
||||
def __init__(self, window, color=(127, 127, 127, 127), samples=240):
|
||||
from time import time
|
||||
from statistics import mean
|
||||
from collections import deque
|
||||
@ -1879,19 +1879,7 @@ class FPSDisplay:
|
||||
|
||||
if self._elapsed >= self.update_period:
|
||||
self._elapsed = 0
|
||||
self._set_fps_text(1 / self._mean(self._delta_times))
|
||||
|
||||
def _set_fps_text(self, fps):
|
||||
"""Set the label text for the given FPS estimation.
|
||||
|
||||
Called by `update` every `update_period` seconds.
|
||||
|
||||
:Parameters:
|
||||
`fps` : float
|
||||
Estimated framerate of the window.
|
||||
|
||||
"""
|
||||
self.label.text = '%.2f' % fps
|
||||
self.label.text = f"{1 / self._mean(self._delta_times):.2f}"
|
||||
|
||||
def draw(self):
|
||||
"""Draw the label."""
|
||||
|
@ -7,7 +7,6 @@
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
|
||||
# input_args = sys.argv
|
||||
|
||||
@ -17,5 +16,5 @@ dllname = "./data_types.dll"
|
||||
|
||||
python_include_path = "C:/Users/shenjack.SHENJACK-5600X/AppData/Local/Programs/Python/Python38/include/"
|
||||
|
||||
os.system("gcc -I {} -shared {} -o {}".format(python_include_path, filename, dllname))
|
||||
# gcc -I C:/Users/shenjack.SHENJACK-5600X/AppData/Local/Programs/Python/Python38/include/ -shared .\data_types.c -o .\data_types.dll
|
||||
os.system("gcc -O3 -I {} -shared {} -o {}".format(python_include_path, filename, dllname))
|
||||
# gcc -I C:/Users/shenjack.SHENJACK-5600X/AppData/Local/Programs/Python/Python38/include/ -shared .\data_types.c -o .\data_types.dll
|
||||
|
1
viz_start.cmd
Normal file
1
viz_start.cmd
Normal file
@ -0,0 +1 @@
|
||||
viztracer --output_file ./logs/viz_result.json --open --tracer_entries 10000000 DR.py
|
Loading…
Reference in New Issue
Block a user