diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index 183be9e..dfc391d 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -11,11 +11,10 @@ github: @shenjackyuanjie gitee: @shenjackyuanjie """ -from libs.semver import VersionInfo +from MCDR.version import Version -game_version = '0.6.2' +game_version = Version("0.6.2") __version__ = game_version -semver_game_version = VersionInfo.parse(game_version) playing = False diff --git a/Difficult_Rocket/api/__init__.py b/Difficult_Rocket/api/__init__.py index a167624..0faf8fc 100644 --- a/Difficult_Rocket/api/__init__.py +++ b/Difficult_Rocket/api/__init__.py @@ -13,11 +13,11 @@ gitee: @shenjackyuanjie # 单独导入的(或者就这一个有用的) from .delivery import Delivery -from .new_thread import new_thread +from utils.new_thread import new_thread # lazy之后之前全部导入的(太多了写不动__all__了) from .Exp import * -from .tools import * +from utils.tools import * from .calculation import * from .scientific_unit import * diff --git a/Difficult_Rocket/api/types/SR1/ship.py b/Difficult_Rocket/api/types/SR1/ship.py new file mode 100644 index 0000000..f04960d --- /dev/null +++ b/Difficult_Rocket/api/types/SR1/ship.py @@ -0,0 +1,21 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" + +# system function +from xml.etree import ElementTree as ET + +# Difficult_Rocket function + +# libs function + + diff --git a/Difficult_Rocket/api/types/__init__.py b/Difficult_Rocket/api/types/__init__.py new file mode 100644 index 0000000..e9da2fb --- /dev/null +++ b/Difficult_Rocket/api/types/__init__.py @@ -0,0 +1,20 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" + +""" +存档模块 +尽量同时兼容SR1和DR +包含: + 解析存档文件 + 创建存档文件 +""" diff --git a/Difficult_Rocket/api/types/data_type.py b/Difficult_Rocket/api/types/data_type.py new file mode 100644 index 0000000..80a03b1 --- /dev/null +++ b/Difficult_Rocket/api/types/data_type.py @@ -0,0 +1,70 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" + +# system function + +# Difficult_Rocket function + +# libs function +from MCDR.serializer import Serializable + +""" +DR 内部数据传输格式类型 +""" + + +# 一艘船的数据格式 +class Ship(Serializable): + data: dict + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + +# 蓝图部件的数据格式 +class Blueprint(Serializable): + data: dict + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + +# 飞船上的单个部件的数据格式 +class Part(Serializable): + data: dict + + def __init__(self, part_type: str, **kwargs): + super().__init__() + self.type = part_type + self.name = kwargs.get('name') + + +# 整个存档的数据格式 +class Save(Serializable): + data: dict + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + +class PartType(Serializable): + data: dict # 输出的数据格式 + + + +# 所有部件的格式的存储 +class PartTypes(Serializable): + data: dict = {} # 所有部件的格式 + + def add_part(self, part_type: str, **kwargs): + self.data[part_type] = Part(part_type, **kwargs) diff --git a/Difficult_Rocket/client.py b/Difficult_Rocket/client/__init__.py similarity index 91% rename from Difficult_Rocket/client.py rename to Difficult_Rocket/client/__init__.py index c859171..b0bb204 100644 --- a/Difficult_Rocket/client.py +++ b/Difficult_Rocket/client/__init__.py @@ -17,7 +17,6 @@ import sys import time import logging import traceback -import configparser from decimal import Decimal @@ -30,9 +29,10 @@ from Difficult_Rocket import translate from Difficult_Rocket.api.Exp import * from Difficult_Rocket.translate import tr from Difficult_Rocket.command import line -from Difficult_Rocket.fps.fps_log import FpsLogger from Difficult_Rocket.guis.widgets import InputBox -from Difficult_Rocket.api import tools, new_thread +from Difficult_Rocket.api import new_thread +from utils import tools +from Difficult_Rocket.client.fps.fps_log import FpsLogger # libs function local_lib = True @@ -40,9 +40,11 @@ if local_lib: from libs import pyglet from libs.pyglet.window import Window from libs.pyglet.window import key, mouse + from libs import toml else: import pyglet from pyglet.window import key, mouse + import toml class Client: @@ -51,7 +53,7 @@ class Client: # logging self.logger = logging.getLogger('client') # config - self.config = tools.load_file('configs/main.config') + self.config = tools.load_file('./configs/main.toml') # value self.process_id = 'Client' self.process_name = 'Client process' @@ -95,9 +97,9 @@ class ClientWindow(Window): # configs pyglet.resource.path = ['/textures/'] pyglet.resource.reindex() - self.set_icon(pyglet.image.load('textures/icon.png')) - self.main_config = tools.load_file('configs/main.config') - self.game_config = tools.load_file('configs/game.config') + self.set_icon(pyglet.image.load('./textures/icon.png')) + self.main_config = tools.load_file('./configs/main.toml') + self.game_config = tools.load_file('./configs/game.config') # dic self.environment = {} self.textures = {} # all textures @@ -156,9 +158,13 @@ class ClientWindow(Window): # 从字体文件夹加载字体(或是字体类文件夹) if os.path.isfile(os.path.join(fonts_folder_path, fonts_folders, files)): # 如果是字体文件,则直接加载 + # self.logger.debug(tr.lang('window', 'fonts.load').format(os.path.join(fonts_folder_path, fonts_folders, files))) pyglet.font.add_file(os.path.join(fonts_folder_path, fonts_folders, files)) else: # 否则,遍历加载字体类文件夹并加载 for font in os.listdir(os.path.join(fonts_folder_path, fonts_folders, files)): + if not font[-4:] == '.ttf': + continue + # self.logger.debug(tr.lang('window', 'fonts.load').format(os.path.join(fonts_folder_path, fonts_folders, files, font))) pyglet.font.add_file(os.path.join(fonts_folder_path, fonts_folders, files, font)) # @new_thread('window load_editor') @@ -187,11 +193,11 @@ class ClientWindow(Window): @new_thread('window save_info') def save_info(self): - config_file = configparser.ConfigParser() - config_file.read('configs/main.config') - config_file['window']['width'] = str(self.width) - config_file['window']['height'] = str(self.height) - config_file.write(open('configs/main.config', 'w', encoding='utf-8')) + print('save_info start') + config_file = tools.load_file('./config/config.toml') + config_file['window']['width'] = self.width + config_file['window']['height'] = self.height + toml.dump(config_file, open('./config/config.toml', 'w')) """ draws and some event diff --git a/Difficult_Rocket/fps/__init__.py b/Difficult_Rocket/client/fps/__init__.py similarity index 100% rename from Difficult_Rocket/fps/__init__.py rename to Difficult_Rocket/client/fps/__init__.py diff --git a/Difficult_Rocket/fps/fps_log.py b/Difficult_Rocket/client/fps/fps_log.py similarity index 86% rename from Difficult_Rocket/fps/fps_log.py rename to Difficult_Rocket/client/fps/fps_log.py index 5798772..e49e03c 100644 --- a/Difficult_Rocket/fps/fps_log.py +++ b/Difficult_Rocket/client/fps/fps_log.py @@ -42,19 +42,17 @@ class FpsLogger: else: self.fps_list.append(1) if len(self.fps_list) > self.count: - self.fps_list = self.fps_list[-self.count + 1:] + self.fps_list = self.fps_list[-self.count + 1:] # 整个列表往前挪一位 if len(self.get_fps_list) > self.count: - self.get_fps_list = self.get_fps_list[-self.count + 1:] + self.get_fps_list = self.get_fps_list[-self.count + 1:] # 整个列表往前挪一位 try: - self._fps = statistics.geometric_mean(self.fps_list[-100:]) - self.middle_fps = statistics.median(self.fps_list) + self._fps = statistics.geometric_mean(self.fps_list[-100:]) # 取最后100个值的平均值 + self.middle_fps = statistics.median(self.fps_list) # 取中间值 except Exception: print(self.fps_list) raise self._max_fps = max(self.fps_list) self._min_fps = min(self.fps_list) - # 获取新fps - del now_fps @property def max_fps(self): diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 0bbd564..70a878b 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -17,14 +17,13 @@ import time import logging import logging.config import multiprocessing -from multiprocessing import Manager as share 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 Difficult_Rocket.api import tools +from utils import tools from Difficult_Rocket.translate import tr diff --git a/Difficult_Rocket/mods/__init__.py b/Difficult_Rocket/mods/__init__.py index 49dae4c..22b1f39 100644 --- a/Difficult_Rocket/mods/__init__.py +++ b/Difficult_Rocket/mods/__init__.py @@ -15,7 +15,7 @@ gitee: @shenjackyuanjie from typing import Tuple # from libs -from semver import VersionInfo +from MCDR.version import Version from MCDR.serializer import Serializable # from DR @@ -25,7 +25,7 @@ from Difficult_Rocket import semver_game_version mod系统参数 """ MOD_loader_version = "0.0.1" # mod系统版本 版本号遵守semver2.0.0 -semver_loader_version = VersionInfo.parse(MOD_loader_version) +semver_loader_version = Version(MOD_loader_version) """ @@ -40,7 +40,7 @@ class MODInfo(Serializable): """ """基本信息""" name: str # mod名称 - version: VersionInfo # mod版本 + version: Version # mod版本 dependencies: list = [] # mod依赖 """作者、描述""" @@ -50,9 +50,9 @@ class MODInfo(Serializable): info: str = "" # 其他信息 (可以很多很多) """版本兼容信息""" - write_version: VersionInfo # mod编写版本 - write_loader_version: VersionInfo # mod编写的加载器版本 - compatible_version: Tuple[VersionInfo, VersionInfo] = (semver_game_version, semver_game_version) # mod兼容版本 + write_version: Version # mod编写版本 + write_loader_version: Version # mod编写的加载器版本 + compatible_version: Tuple[Version, Version] = (semver_game_version, semver_game_version) # mod兼容版本 # 第一个是最低兼容版本,第二个是最高兼容版本 # 例如: ("1.0.0", "1.1.0") 表示从1.0.0版本开始兼容,到1.1.0版本结束兼容 diff --git a/Difficult_Rocket/server.py b/Difficult_Rocket/server/__init__.py similarity index 90% rename from Difficult_Rocket/server.py rename to Difficult_Rocket/server/__init__.py index 55c6617..ef5f237 100644 --- a/Difficult_Rocket/server.py +++ b/Difficult_Rocket/server/__init__.py @@ -1,4 +1,4 @@ -# ------------------------------- +# ------------------------------- # Difficult Rocket # Copyright © 2021-2022 by shenjackyuanjie # All rights reserved @@ -11,17 +11,17 @@ github: @shenjackyuanjie gitee: @shenjackyuanjie """ -import logging import os import sys +import logging if __name__ == '__main__': # been start will not run this sys.path.append('/bin/libs') sys.path.append('/bin') -from Difficult_Rocket.api import tools +from utils import tools from Difficult_Rocket.api.delivery import Delivery -from Difficult_Rocket.api.new_thread import new_thread +from utils.new_thread import new_thread # TODO 改变服务端启动逻辑 0.6.0会写完的( diff --git a/Difficult_Rocket/translate.py b/Difficult_Rocket/translate.py index a7d8a16..46b26f1 100644 --- a/Difficult_Rocket/translate.py +++ b/Difficult_Rocket/translate.py @@ -13,7 +13,7 @@ gitee: @shenjackyuanjie from typing import Union -from Difficult_Rocket.api import tools +from utils import tools from Difficult_Rocket.api.Exp import * """ diff --git a/Difficult_Rocket/unpack_textures.py b/Difficult_Rocket/unpack_textures.py index 7f796d5..4efcd8e 100644 --- a/Difficult_Rocket/unpack_textures.py +++ b/Difficult_Rocket/unpack_textures.py @@ -11,7 +11,7 @@ github: @shenjackyuanjie gitee: @shenjackyuanjie """ -from Difficult_Rocket.api import tools +from utils import tools import os import PIL.Image diff --git a/Difficult_Rocket/utils/__init__.py b/Difficult_Rocket/utils/__init__.py new file mode 100644 index 0000000..43badfc --- /dev/null +++ b/Difficult_Rocket/utils/__init__.py @@ -0,0 +1,12 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" diff --git a/Difficult_Rocket/api/new_thread.py b/Difficult_Rocket/utils/new_thread.py similarity index 100% rename from Difficult_Rocket/api/new_thread.py rename to Difficult_Rocket/utils/new_thread.py diff --git a/Difficult_Rocket/api/thread.py b/Difficult_Rocket/utils/thread.py similarity index 100% rename from Difficult_Rocket/api/thread.py rename to Difficult_Rocket/utils/thread.py diff --git a/Difficult_Rocket/api/tools.py b/Difficult_Rocket/utils/tools.py similarity index 91% rename from Difficult_Rocket/api/tools.py rename to Difficult_Rocket/utils/tools.py index 4977646..c8c63b8 100644 --- a/Difficult_Rocket/api/tools.py +++ b/Difficult_Rocket/utils/tools.py @@ -21,9 +21,11 @@ import configparser from xml.dom.minidom import parse -if __name__ == '__main__': # been start will not run this - sys.path.append('/bin/libs') - sys.path.append('/bin') +if __name__ == '__main__': # 如果是直接运行该文件,则将工作目录切换到该文件所在目录 + sys.path.append('./libs') + sys.path.append('./') + +import toml from libs import json5 @@ -38,31 +40,31 @@ file_error = {'FileNotFoundError': 'no {filetype} file was founded!:\n file name 'Error': 'get some unknown error when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'} -def load_file(file_name: str, stack=None) -> dict: +def load_file(file_name: str, stack=None): f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式) try: - rd = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!') + 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 - rd = json5.load(jf, encoding='uft-8') + get_file = json5.load(jf, encoding='uft-8') except UnicodeDecodeError: with open(file_name, 'r', encoding='gbk') as jf: - rd = json5.load(jf) + get_file = json5.load(jf) tools_logger.info('文件 %s 解码错误,已重新使用gbk编码打开' % file_name) if stack is not None: - rd = rd[stack] + get_file = get_file[stack] elif f_type == 'xml': xml_load = parse(file_name) if stack is not None: - rd = xml_load.getElementsByTagName(stack) + get_file = xml_load.getElementsByTagName(stack) elif (f_type == 'config') or (f_type == 'conf') or (f_type == 'ini'): - cd = configparser.ConfigParser() - cd.read(file_name) + get_file = configparser.ConfigParser() + get_file.read(file_name) if stack: - rd = cd[stack] - else: - rd = cd + get_file = get_file[stack] + elif f_type == 'toml': + get_file = toml.load(file_name) except Exception as exp: error_type = type(exp).__name__ if error_type in file_error: @@ -70,7 +72,7 @@ def load_file(file_name: str, stack=None) -> dict: else: tools_logger.error(file_error['Error'].format(filetype=f_type, filename=file_name, stack=stack)) raise - return rd + return get_file # main config diff --git a/configs/lang/zh-CN.json5 b/configs/lang/zh-CN.json5 index db7a9c9..174fb5c 100644 --- a/configs/lang/zh-CN.json5 +++ b/configs/lang/zh-CN.json5 @@ -41,6 +41,7 @@ 'libs.local': '正在使用本地 pyglet 库 版本为: {}', 'libs.outer': '正在使用全局 pyglet 库 版本为: {}\n(可能会造成bug,因为本地库版本为2.0dev9)', 'fonts.found': '在字体列表中找到以下字体库: {}', + 'fonts.load': '正在加载字体: {}', 'game.input_stop': '控制台', 'game.command_stop': '游戏内命令行', 'game.window_stop': '窗口', diff --git a/configs/main.toml b/configs/main.toml new file mode 100644 index 0000000..c1dac4e --- /dev/null +++ b/configs/main.toml @@ -0,0 +1,21 @@ +[runtime] +fps = 60 +version = "0.6.1" +language = "zh-CN" +date_fmt = '%Y-%m-%d %H-%M-%S' +write_py_v = "3.8.10" +fonts_folder = 'libs/fonts' + +[window] +style = "None" +width = 1300 +height = 931 +visible = true +caption = "Difficult Rocket {version}" +resizable = true +full_screen = false + +[window.default] +width = 1024 +height = 768 + diff --git a/docs/howto/game/命名.md b/docs/howto/game/命名.md new file mode 100644 index 0000000..6235f90 --- /dev/null +++ b/docs/howto/game/命名.md @@ -0,0 +1,49 @@ +# 关于命名的设计文档 + +## 命名规则 + +## 命名空间 + +- DR: Difficult Rocket + - DR单独的部件、格式、结构的命名空间 + - 例子 + - `DR:pod-1` + - `DR:solar.expand` + - `DR:wheel.big` + - `DR:planet.smearth` + - `DR:planet.smars` +- SR: SimpleRockets + - SR的原生组件、格式、结构的命名空间(大概不会用多少) + - 例子 + - `SR:pod-1` + - `SR:wheel.small` +- 其他: + - 命名规则: + - 可以包含 + - `ABC` + - `abc` + - `-` `_` + - `123` + - `从前有座山` + - `Unicode表情` + - 各种中文标点符号 + - 中文的啊! + - `,` `。` `、` `·` + - `;` `:` + - `?` `!` + - `(` `)` + - `【` `】` + - `《` `》` + - `“` `”` + - `‘` `’` + - 不能以数字开头 + - 不能包含 + - `.` `/` `:` + - `<` `>` + - `|` `*` `?` + - `"` `'` + - 例子: + - `Simple_Mod` + - `真·简单mod` + - `啊啊啊啊,↑↓Jundroo!` +- mod添加的部件、格式、结构的命名空间 diff --git a/docs/howto/mod/loader.md b/docs/howto/mod/loader.md new file mode 100644 index 0000000..546469a --- /dev/null +++ b/docs/howto/mod/loader.md @@ -0,0 +1,15 @@ +# MOD加载器设计文档 + +## v1-20220307 + +### __init__.py + +- MODInfo类 + - MODInfo类的属性 + - 一些基本的MOD信息 + - 版本类信息 + - MOD版本号 + - DR MOD加载器兼容版本 + - DR 内容兼容版本 + - 需要的MOD版本号 + - diff --git a/docs/update_logs.md b/docs/update_logs.md index 81a99a1..3ac75b5 100644 --- a/docs/update_logs.md +++ b/docs/update_logs.md @@ -19,9 +19,13 @@ ### Add -- 添加模块 `semver` 和协议 (`LICENSE.txt`) - - Add modules `semver` Add LICENSE (`LICENSE.txt`) +[然后就很快被替换成MCDR的了]: <> (- 添加模块 `semver` 和协议 (`LICENSE.txt`)) +[Add soon been replace by MCDR]: <> ( - Add modules `semver` Add LICENSE (`LICENSE.txt`)) +- 添加了 `libs.MCDR` 文件夹 (`new_thread`没有包含在内) + - Add `libs.MCDR` folder (`new_thread` not included) - 添加对 mod 的支持(还在写啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊) +- 计划写个设计文档 + - Plan to write a design document ## ~~202111 202112xx 20220119~~ 20220207 V 0.6.1 diff --git a/libs/MCDR/serializer.py b/libs/MCDR/serializer.py index 34ae479..1f3a9d4 100644 --- a/libs/MCDR/serializer.py +++ b/libs/MCDR/serializer.py @@ -1,5 +1,6 @@ # 本文件以 GNU Lesser General Public License v3.0(GNU LGPL v3) 开源协议进行授权 (谢谢狐狸写出这么好的MCDR) # 顺便说一句,我把所有的tab都改成了空格,因为我觉得空格比tab更好看(草,后半句是github copilot自动填充的) +# 节选自MCDReforged(5a92965,2022年1月),略有改动[doge] import copy from abc import ABC @@ -7,8 +8,7 @@ from enum import EnumMeta from threading import Lock from typing import Union, TypeVar, List, Dict, Type, get_type_hints, Any -from semver import VersionInfo as semver_VersionInfo -from libs.semver import VersionInfo as lib_semver_VersionInfo +from MCDR.version import Version """ This part of code come from MCDReforged(https://github.com/Fallen-Breath/MCDReforged) @@ -41,13 +41,13 @@ def _get_args(cls: Type) -> tuple: return getattr(cls, '__args__', ()) -_BASIC_CLASSES = (type(None), bool, int, float, str, list, dict, lib_semver_VersionInfo, semver_VersionInfo) +_BASIC_CLASSES = (type(None), bool, int, float, str, list, dict, Version) def serialize(obj) -> _BASIC_CLASSES: if type(obj) in (type(None), int, float, str, bool): return obj - elif isinstance(obj, lib_semver_VersionInfo) or isinstance(obj, semver_VersionInfo): + elif isinstance(obj, Version): return obj elif isinstance(obj, list) or isinstance(obj, tuple): return list(map(serialize, obj)) @@ -87,6 +87,9 @@ def deserialize(data, cls: Type[T], *, error_at_missing=False, error_at_redundan # For list and dict, since it doesn't have any type hint, we choose to simply return the data elif cls in _BASIC_CLASSES and type(data) is cls: return data + # Version + elif isinstance(cls, Version): + return data # float thing elif cls is float and isinstance(data, int): return float(data) diff --git a/libs/MCDR/Version.py b/libs/MCDR/version.py similarity index 100% rename from libs/MCDR/Version.py rename to libs/MCDR/version.py diff --git a/libs/semver/LICENSE.txt b/libs/semver/LICENSE.txt deleted file mode 100644 index f98e22b..0000000 --- a/libs/semver/LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013, Konstantine Rybnikov -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the {organization} nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/semver/__init__.py b/libs/semver/__init__.py deleted file mode 100644 index 2b6dae1..0000000 --- a/libs/semver/__init__.py +++ /dev/null @@ -1,1258 +0,0 @@ -"""Python helper for Semantic Versioning (http://semver.org/)""" -from __future__ import print_function - -import argparse -import collections -from functools import wraps, partial -import inspect -import re -import sys -import warnings - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -__version__ = "2.13.0" -__author__ = "Kostiantyn Rybnikov" -__author_email__ = "k-bx@k-bx.com" -__maintainer__ = ["Sebastien Celles", "Tom Schraitle"] -__maintainer_email__ = "s.celles@gmail.com" - -#: Our public interface -__all__ = ( - # - # Module level function: - "bump_build", - "bump_major", - "bump_minor", - "bump_patch", - "bump_prerelease", - "compare", - "deprecated", - "finalize_version", - "format_version", - "match", - "max_ver", - "min_ver", - "parse", - "parse_version_info", - "replace", - # - # CLI interface - "cmd_bump", - "cmd_check", - "cmd_compare", - "createparser", - "main", - "process", - # - # Constants and classes - "SEMVER_SPEC_VERSION", - "VersionInfo", -) - -#: Contains the implemented semver.org version of the spec -SEMVER_SPEC_VERSION = "2.0.0" - -if not hasattr(__builtins__, "cmp"): - def cmp(a, b): - """Return negative if ab.""" - return (a > b) - (a < b) - -if PY3: # pragma: no cover - string_types = str, bytes - text_type = str - binary_type = bytes - - - def b(s): - return s.encode("latin-1") - - - def u(s): - return s - - -else: # pragma: no cover - string_types = unicode, str - text_type = unicode - binary_type = str - - - def b(s): - return s - - - # Workaround for standalone backslash - def u(s): - return unicode(s.replace(r"\\", r"\\\\"), "unicode_escape") - - -def ensure_str(s, encoding="utf-8", errors="strict"): - # Taken from six project - """ - Coerce *s* to `str`. - - For Python 2: - - `unicode` -> encoded to `str` - - `str` -> `str` - - For Python 3: - - `str` -> `str` - - `bytes` -> decoded to `str` - """ - if not isinstance(s, (text_type, binary_type)): - raise TypeError("not expecting type '%s'" % type(s)) - if PY2 and isinstance(s, text_type): - s = s.encode(encoding, errors) - elif PY3 and isinstance(s, binary_type): - s = s.decode(encoding, errors) - return s - - -def deprecated(func=None, replace=None, version=None, category=DeprecationWarning): - """ - Decorates a function to output a deprecation warning. - - :param func: the function to decorate (or None) - :param str replace: the function to replace (use the full qualified - name like ``semver.VersionInfo.bump_major``. - :param str version: the first version when this function was deprecated. - :param category: allow you to specify the deprecation warning class - of your choice. By default, it's :class:`DeprecationWarning`, but - you can choose :class:`PendingDeprecationWarning` or a custom class. - """ - - if func is None: - return partial(deprecated, replace=replace, version=version, category=category) - - @wraps(func) - def wrapper(*args, **kwargs): - msg = ["Function '{m}.{f}' is deprecated."] - - if version: - msg.append("Deprecated since version {v}. ") - msg.append("This function will be removed in semver 3.") - if replace: - msg.append("Use {r!r} instead.") - else: - msg.append("Use the respective 'semver.VersionInfo.{r}' instead.") - - # hasattr is needed for Python2 compatibility: - f = func.__qualname__ if hasattr(func, "__qualname__") else func.__name__ - r = replace or f - - frame = inspect.currentframe().f_back - - msg = " ".join(msg) - warnings.warn_explicit( - msg.format(m=func.__module__, f=f, r=r, v=version), - category=category, - filename=inspect.getfile(frame.f_code), - lineno=frame.f_lineno, - ) - # As recommended in the Python documentation - # https://docs.python.org/3/library/inspect.html#the-interpreter-stack - # better remove the interpreter stack: - del frame - return func(*args, **kwargs) - - return wrapper - - -@deprecated(version="2.10.0") -def parse(version): - """ - Parse version to major, minor, patch, pre-release, build parts. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.parse` instead. - - :param version: version string - :return: dictionary with the keys 'build', 'major', 'minor', 'patch', - and 'prerelease'. The prerelease or build keys can be None - if not provided - :rtype: dict - - >>> ver = semver.parse('3.4.5-pre.2+build.4') - >>> ver['major'] - 3 - >>> ver['minor'] - 4 - >>> ver['patch'] - 5 - >>> ver['prerelease'] - 'pre.2' - >>> ver['build'] - 'build.4' - """ - return VersionInfo.parse(version).to_dict() - - -def comparator(operator): - """Wrap a VersionInfo binary op method in a type-check.""" - - @wraps(operator) - def wrapper(self, other): - comparable_types = (VersionInfo, dict, tuple, list, text_type, binary_type) - if not isinstance(other, comparable_types): - raise TypeError( - "other type %r must be in %r" % (type(other), comparable_types) - ) - return operator(self, other) - - return wrapper - - -class VersionInfo(object): - """ - A semver compatible version class. - - :param int major: version when you make incompatible API changes. - :param int minor: version when you add functionality in - a backwards-compatible manner. - :param int patch: version when you make backwards-compatible bug fixes. - :param str prerelease: an optional prerelease string - :param str build: an optional build string - """ - - __slots__ = ("_major", "_minor", "_patch", "_prerelease", "_build") - #: Regex for number in a prerelease - _LAST_NUMBER = re.compile(r"(?:[^\d]*(\d+)[^\d]*)+") - #: Regex for a semver version - _REGEX = re.compile( - r""" - ^ - (?P0|[1-9]\d*) - \. - (?P0|[1-9]\d*) - \. - (?P0|[1-9]\d*) - (?:-(?P - (?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*) - (?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))* - ))? - (?:\+(?P - [0-9a-zA-Z-]+ - (?:\.[0-9a-zA-Z-]+)* - ))? - $ - """, - re.VERBOSE, - ) - - def __init__(self, major, minor=0, patch=0, prerelease=None, build=None): - # Build a dictionary of the arguments except prerelease and build - version_parts = { - "major": major, - "minor": minor, - "patch": patch, - } - - for name, value in version_parts.items(): - value = int(value) - version_parts[name] = value - if value < 0: - raise ValueError( - "{!r} is negative. A version can only be positive.".format(name) - ) - - self._major = version_parts["major"] - self._minor = version_parts["minor"] - self._patch = version_parts["patch"] - self._prerelease = None if prerelease is None else str(prerelease) - self._build = None if build is None else str(build) - - @property - def major(self): - """The major part of a version (read-only).""" - return self._major - - @major.setter - def major(self, value): - raise AttributeError("attribute 'major' is readonly") - - @property - def minor(self): - """The minor part of a version (read-only).""" - return self._minor - - @minor.setter - def minor(self, value): - raise AttributeError("attribute 'minor' is readonly") - - @property - def patch(self): - """The patch part of a version (read-only).""" - return self._patch - - @patch.setter - def patch(self, value): - raise AttributeError("attribute 'patch' is readonly") - - @property - def prerelease(self): - """The prerelease part of a version (read-only).""" - return self._prerelease - - @prerelease.setter - def prerelease(self, value): - raise AttributeError("attribute 'prerelease' is readonly") - - @property - def build(self): - """The build part of a version (read-only).""" - return self._build - - @build.setter - def build(self, value): - raise AttributeError("attribute 'build' is readonly") - - def to_tuple(self): - """ - Convert the VersionInfo object to a tuple. - - .. versionadded:: 2.10.0 - Renamed ``VersionInfo._astuple`` to ``VersionInfo.to_tuple`` to - make this function available in the public API. - - :return: a tuple with all the parts - :rtype: tuple - - >>> semver.VersionInfo(5, 3, 1).to_tuple() - (5, 3, 1, None, None) - """ - return (self.major, self.minor, self.patch, self.prerelease, self.build) - - def to_dict(self): - """ - Convert the VersionInfo object to an OrderedDict. - - .. versionadded:: 2.10.0 - Renamed ``VersionInfo._asdict`` to ``VersionInfo.to_dict`` to - make this function available in the public API. - - :return: an OrderedDict with the keys in the order ``major``, ``minor``, - ``patch``, ``prerelease``, and ``build``. - :rtype: :class:`collections.OrderedDict` - - >>> semver.VersionInfo(3, 2, 1).to_dict() - OrderedDict([('major', 3), ('minor', 2), ('patch', 1), \ -('prerelease', None), ('build', None)]) - """ - return collections.OrderedDict( - ( - ("major", self.major), - ("minor", self.minor), - ("patch", self.patch), - ("prerelease", self.prerelease), - ("build", self.build), - ) - ) - - # For compatibility reasons: - @deprecated(replace="semver.VersionInfo.to_tuple", version="2.10.0") - def _astuple(self): - return self.to_tuple() # pragma: no cover - - _astuple.__doc__ = to_tuple.__doc__ - - @deprecated(replace="semver.VersionInfo.to_dict", version="2.10.0") - def _asdict(self): - return self.to_dict() # pragma: no cover - - _asdict.__doc__ = to_dict.__doc__ - - def __iter__(self): - """Implement iter(self).""" - # As long as we support Py2.7, we can't use the "yield from" syntax - for v in self.to_tuple(): - yield v - - @staticmethod - def _increment_string(string): - """ - Look for the last sequence of number(s) in a string and increment. - - :param str string: the string to search for. - :return: the incremented string - - Source: - http://code.activestate.com/recipes/442460-increment-numbers-in-a-string/#c1 - """ - match = VersionInfo._LAST_NUMBER.search(string) - if match: - next_ = str(int(match.group(1)) + 1) - start, end = match.span(1) - string = string[: max(end - len(next_), start)] + next_ + string[end:] - return string - - def bump_major(self): - """ - Raise the major part of the version, return a new object but leave self - untouched. - - :return: new object with the raised major part - :rtype: :class:`VersionInfo` - - >>> ver = semver.VersionInfo.parse("3.4.5") - >>> ver.bump_major() - VersionInfo(major=4, minor=0, patch=0, prerelease=None, build=None) - """ - cls = type(self) - return cls(self._major + 1) - - def bump_minor(self): - """ - Raise the minor part of the version, return a new object but leave self - untouched. - - :return: new object with the raised minor part - :rtype: :class:`VersionInfo` - - >>> ver = semver.VersionInfo.parse("3.4.5") - >>> ver.bump_minor() - VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None) - """ - cls = type(self) - return cls(self._major, self._minor + 1) - - def bump_patch(self): - """ - Raise the patch part of the version, return a new object but leave self - untouched. - - :return: new object with the raised patch part - :rtype: :class:`VersionInfo` - - >>> ver = semver.VersionInfo.parse("3.4.5") - >>> ver.bump_patch() - VersionInfo(major=3, minor=4, patch=6, prerelease=None, build=None) - """ - cls = type(self) - return cls(self._major, self._minor, self._patch + 1) - - def bump_prerelease(self, token="rc"): - """ - Raise the prerelease part of the version, return a new object but leave - self untouched. - - :param token: defaults to 'rc' - :return: new object with the raised prerelease part - :rtype: :class:`VersionInfo` - - >>> ver = semver.VersionInfo.parse("3.4.5-rc.1") - >>> ver.bump_prerelease() - VersionInfo(major=3, minor=4, patch=5, prerelease='rc.2', \ -build=None) - """ - cls = type(self) - prerelease = cls._increment_string(self._prerelease or (token or "rc") + ".0") - return cls(self._major, self._minor, self._patch, prerelease) - - def bump_build(self, token="build"): - """ - Raise the build part of the version, return a new object but leave self - untouched. - - :param token: defaults to 'build' - :return: new object with the raised build part - :rtype: :class:`VersionInfo` - - >>> ver = semver.VersionInfo.parse("3.4.5-rc.1+build.9") - >>> ver.bump_build() - VersionInfo(major=3, minor=4, patch=5, prerelease='rc.1', \ -build='build.10') - """ - cls = type(self) - build = cls._increment_string(self._build or (token or "build") + ".0") - return cls(self._major, self._minor, self._patch, self._prerelease, build) - - def compare(self, other): - """ - Compare self with other. - - :param other: the second version (can be string, a dict, tuple/list, or - a VersionInfo instance) - :return: The return value is negative if ver1 < ver2, - zero if ver1 == ver2 and strictly positive if ver1 > ver2 - :rtype: int - - >>> semver.VersionInfo.parse("1.0.0").compare("2.0.0") - -1 - >>> semver.VersionInfo.parse("2.0.0").compare("1.0.0") - 1 - >>> semver.VersionInfo.parse("2.0.0").compare("2.0.0") - 0 - >>> semver.VersionInfo.parse("2.0.0").compare(dict(major=2, minor=0, patch=0)) - 0 - """ - cls = type(self) - if isinstance(other, string_types): - other = cls.parse(other) - elif isinstance(other, dict): - other = cls(**other) - elif isinstance(other, (tuple, list)): - other = cls(*other) - elif not isinstance(other, cls): - raise TypeError( - "Expected str or {} instance, but got {}".format( - cls.__name__, type(other) - ) - ) - - v1 = self.to_tuple()[:3] - v2 = other.to_tuple()[:3] - x = cmp(v1, v2) - if x: - return x - - rc1, rc2 = self.prerelease, other.prerelease - rccmp = _nat_cmp(rc1, rc2) - - if not rccmp: - return 0 - if not rc1: - return 1 - elif not rc2: - return -1 - - return rccmp - - def next_version(self, part, prerelease_token="rc"): - """ - Determines next version, preserving natural order. - - .. versionadded:: 2.10.0 - - This function is taking prereleases into account. - The "major", "minor", and "patch" raises the respective parts like - the ``bump_*`` functions. The real difference is using the - "preprelease" part. It gives you the next patch version of the prerelease, - for example: - - >>> str(semver.VersionInfo.parse("0.1.4").next_version("prerelease")) - '0.1.5-rc.1' - - :param part: One of "major", "minor", "patch", or "prerelease" - :param prerelease_token: prefix string of prerelease, defaults to 'rc' - :return: new object with the appropriate part raised - :rtype: :class:`VersionInfo` - """ - validparts = { - "major", - "minor", - "patch", - "prerelease", - # "build", # currently not used - } - if part not in validparts: - raise ValueError( - "Invalid part. Expected one of {validparts}, but got {part!r}".format( - validparts=validparts, part=part - ) - ) - version = self - if (version.prerelease or version.build) and ( - part == "patch" - or (part == "minor" and version.patch == 0) - or (part == "major" and version.minor == version.patch == 0) - ): - return version.replace(prerelease=None, build=None) - - if part in ("major", "minor", "patch"): - return getattr(version, "bump_" + part)() - - if not version.prerelease: - version = version.bump_patch() - return version.bump_prerelease(prerelease_token) - - @comparator - def __eq__(self, other): - return self.compare(other) == 0 - - @comparator - def __ne__(self, other): - return self.compare(other) != 0 - - @comparator - def __lt__(self, other): - return self.compare(other) < 0 - - @comparator - def __le__(self, other): - return self.compare(other) <= 0 - - @comparator - def __gt__(self, other): - return self.compare(other) > 0 - - @comparator - def __ge__(self, other): - return self.compare(other) >= 0 - - def __getitem__(self, index): - """ - self.__getitem__(index) <==> self[index] - - Implement getitem. If the part requested is undefined, or a part of the - range requested is undefined, it will throw an index error. - Negative indices are not supported - - :param Union[int, slice] index: a positive integer indicating the - offset or a :func:`slice` object - :raises: IndexError, if index is beyond the range or a part is None - :return: the requested part of the version at position index - - >>> ver = semver.VersionInfo.parse("3.4.5") - >>> ver[0], ver[1], ver[2] - (3, 4, 5) - """ - if isinstance(index, int): - index = slice(index, index + 1) - - if ( - isinstance(index, slice) - and (index.start is not None and index.start < 0) - or (index.stop is not None and index.stop < 0) - ): - raise IndexError("Version index cannot be negative") - - part = tuple(filter(lambda p: p is not None, self.to_tuple()[index])) - - if len(part) == 1: - part = part[0] - elif not part: - raise IndexError("Version part undefined") - return part - - def __repr__(self): - s = ", ".join("%s=%r" % (key, val) for key, val in self.to_dict().items()) - return "%s(%s)" % (type(self).__name__, s) - - def __str__(self): - """str(self)""" - version = "%d.%d.%d" % (self.major, self.minor, self.patch) - if self.prerelease: - version += "-%s" % self.prerelease - if self.build: - version += "+%s" % self.build - return version - - def __hash__(self): - return hash(self.to_tuple()[:4]) - - def finalize_version(self): - """ - Remove any prerelease and build metadata from the version. - - :return: a new instance with the finalized version string - :rtype: :class:`VersionInfo` - - >>> str(semver.VersionInfo.parse('1.2.3-rc.5').finalize_version()) - '1.2.3' - """ - cls = type(self) - return cls(self.major, self.minor, self.patch) - - def match(self, match_expr): - """ - Compare self to match a match expression. - - :param str match_expr: operator and version; valid operators are - < smaller than - > greater than - >= greator or equal than - <= smaller or equal than - == equal - != not equal - :return: True if the expression matches the version, otherwise False - :rtype: bool - - >>> semver.VersionInfo.parse("2.0.0").match(">=1.0.0") - True - >>> semver.VersionInfo.parse("1.0.0").match(">1.0.0") - False - """ - prefix = match_expr[:2] - if prefix in (">=", "<=", "==", "!="): - match_version = match_expr[2:] - elif prefix and prefix[0] in (">", "<"): - prefix = prefix[0] - match_version = match_expr[1:] - else: - raise ValueError( - "match_expr parameter should be in format , " - "where is one of " - "['<', '>', '==', '<=', '>=', '!=']. " - "You provided: %r" % match_expr - ) - - possibilities_dict = { - ">": (1,), - "<": (-1,), - "==": (0,), - "!=": (-1, 1), - ">=": (0, 1), - "<=": (-1, 0), - } - - possibilities = possibilities_dict[prefix] - cmp_res = self.compare(match_version) - - return cmp_res in possibilities - - @classmethod - def parse(cls, version): - """ - Parse version string to a VersionInfo instance. - - :param version: version string - :return: a :class:`VersionInfo` instance - :raises: :class:`ValueError` - :rtype: :class:`VersionInfo` - - .. versionchanged:: 2.11.0 - Changed method from static to classmethod to - allow subclasses. - - >>> semver.VersionInfo.parse('3.4.5-pre.2+build.4') - VersionInfo(major=3, minor=4, patch=5, \ -prerelease='pre.2', build='build.4') - """ - match = cls._REGEX.match(ensure_str(version)) - if match is None: - raise ValueError("%s is not valid SemVer string" % version) - - version_parts = match.groupdict() - - version_parts["major"] = int(version_parts["major"]) - version_parts["minor"] = int(version_parts["minor"]) - version_parts["patch"] = int(version_parts["patch"]) - - return cls(**version_parts) - - def replace(self, **parts): - """ - Replace one or more parts of a version and return a new - :class:`VersionInfo` object, but leave self untouched - - .. versionadded:: 2.9.0 - Added :func:`VersionInfo.replace` - - :param dict parts: the parts to be updated. Valid keys are: - ``major``, ``minor``, ``patch``, ``prerelease``, or ``build`` - :return: the new :class:`VersionInfo` object with the changed - parts - :raises: :class:`TypeError`, if ``parts`` contains invalid keys - """ - version = self.to_dict() - version.update(parts) - try: - return VersionInfo(**version) - except TypeError: - unknownkeys = set(parts) - set(self.to_dict()) - error = "replace() got %d unexpected keyword " "argument(s): %s" % ( - len(unknownkeys), - ", ".join(unknownkeys), - ) - raise TypeError(error) - - @classmethod - def isvalid(cls, version): - """ - Check if the string is a valid semver version. - - .. versionadded:: 2.9.1 - - :param str version: the version string to check - :return: True if the version string is a valid semver version, False - otherwise. - :rtype: bool - """ - try: - cls.parse(version) - return True - except ValueError: - return False - - -@deprecated(replace="semver.VersionInfo.parse", version="2.10.0") -def parse_version_info(version): - """ - Parse version string to a VersionInfo instance. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.parse` instead. - - .. versionadded:: 2.7.2 - Added :func:`semver.parse_version_info` - - :param version: version string - :return: a :class:`VersionInfo` instance - :rtype: :class:`VersionInfo` - - >>> version_info = semver.VersionInfo.parse("3.4.5-pre.2+build.4") - >>> version_info.major - 3 - >>> version_info.minor - 4 - >>> version_info.patch - 5 - >>> version_info.prerelease - 'pre.2' - >>> version_info.build - 'build.4' - """ - return VersionInfo.parse(version) - - -def _nat_cmp(a, b): - def convert(text): - return int(text) if re.match("^[0-9]+$", text) else text - - def split_key(key): - return [convert(c) for c in key.split(".")] - - def cmp_prerelease_tag(a, b): - if isinstance(a, int) and isinstance(b, int): - return cmp(a, b) - elif isinstance(a, int): - return -1 - elif isinstance(b, int): - return 1 - else: - return cmp(a, b) - - a, b = a or "", b or "" - a_parts, b_parts = split_key(a), split_key(b) - for sub_a, sub_b in zip(a_parts, b_parts): - cmp_result = cmp_prerelease_tag(sub_a, sub_b) - if cmp_result != 0: - return cmp_result - else: - return cmp(len(a), len(b)) - - -@deprecated(version="2.10.0") -def compare(ver1, ver2): - """ - Compare two versions strings. - - :param ver1: version string 1 - :param ver2: version string 2 - :return: The return value is negative if ver1 < ver2, - zero if ver1 == ver2 and strictly positive if ver1 > ver2 - :rtype: int - - >>> semver.compare("1.0.0", "2.0.0") - -1 - >>> semver.compare("2.0.0", "1.0.0") - 1 - >>> semver.compare("2.0.0", "2.0.0") - 0 - """ - v1 = VersionInfo.parse(ver1) - return v1.compare(ver2) - - -@deprecated(version="2.10.0") -def match(version, match_expr): - """ - Compare two versions strings through a comparison. - - :param str version: a version string - :param str match_expr: operator and version; valid operators are - < smaller than - > greater than - >= greator or equal than - <= smaller or equal than - == equal - != not equal - :return: True if the expression matches the version, otherwise False - :rtype: bool - - >>> semver.match("2.0.0", ">=1.0.0") - True - >>> semver.match("1.0.0", ">1.0.0") - False - """ - ver = VersionInfo.parse(version) - return ver.match(match_expr) - - -@deprecated(replace="max", version="2.10.2") -def max_ver(ver1, ver2): - """ - Returns the greater version of two versions strings. - - :param ver1: version string 1 - :param ver2: version string 2 - :return: the greater version of the two - :rtype: :class:`VersionInfo` - - >>> semver.max_ver("1.0.0", "2.0.0") - '2.0.0' - """ - if isinstance(ver1, string_types): - ver1 = VersionInfo.parse(ver1) - elif not isinstance(ver1, VersionInfo): - raise TypeError() - cmp_res = ver1.compare(ver2) - if cmp_res >= 0: - return str(ver1) - else: - return ver2 - - -@deprecated(replace="min", version="2.10.2") -def min_ver(ver1, ver2): - """ - Returns the smaller version of two versions strings. - - :param ver1: version string 1 - :param ver2: version string 2 - :return: the smaller version of the two - :rtype: :class:`VersionInfo` - - >>> semver.min_ver("1.0.0", "2.0.0") - '1.0.0' - """ - ver1 = VersionInfo.parse(ver1) - cmp_res = ver1.compare(ver2) - if cmp_res <= 0: - return str(ver1) - else: - return ver2 - - -@deprecated(replace="str(versionobject)", version="2.10.0") -def format_version(major, minor, patch, prerelease=None, build=None): - """ - Format a version string according to the Semantic Versioning specification. - - .. deprecated:: 2.10.0 - Use ``str(VersionInfo(VERSION)`` instead. - - :param int major: the required major part of a version - :param int minor: the required minor part of a version - :param int patch: the required patch part of a version - :param str prerelease: the optional prerelease part of a version - :param str build: the optional build part of a version - :return: the formatted string - :rtype: str - - >>> semver.format_version(3, 4, 5, 'pre.2', 'build.4') - '3.4.5-pre.2+build.4' - """ - return str(VersionInfo(major, minor, patch, prerelease, build)) - - -@deprecated(version="2.10.0") -def bump_major(version): - """ - Raise the major part of the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.bump_major` instead. - - :param: version string - :return: the raised version string - :rtype: str - - >>> semver.bump_major("3.4.5") - '4.0.0' - """ - return str(VersionInfo.parse(version).bump_major()) - - -@deprecated(version="2.10.0") -def bump_minor(version): - """ - Raise the minor part of the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.bump_minor` instead. - - :param: version string - :return: the raised version string - :rtype: str - - >>> semver.bump_minor("3.4.5") - '3.5.0' - """ - return str(VersionInfo.parse(version).bump_minor()) - - -@deprecated(version="2.10.0") -def bump_patch(version): - """ - Raise the patch part of the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.bump_patch` instead. - - :param: version string - :return: the raised version string - :rtype: str - - >>> semver.bump_patch("3.4.5") - '3.4.6' - """ - return str(VersionInfo.parse(version).bump_patch()) - - -@deprecated(version="2.10.0") -def bump_prerelease(version, token="rc"): - """ - Raise the prerelease part of the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.bump_prerelease` instead. - - :param version: version string - :param token: defaults to 'rc' - :return: the raised version string - :rtype: str - - >>> semver.bump_prerelease('3.4.5', 'dev') - '3.4.5-dev.1' - """ - return str(VersionInfo.parse(version).bump_prerelease(token)) - - -@deprecated(version="2.10.0") -def bump_build(version, token="build"): - """ - Raise the build part of the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.bump_build` instead. - - :param version: version string - :param token: defaults to 'build' - :return: the raised version string - :rtype: str - - >>> semver.bump_build('3.4.5-rc.1+build.9') - '3.4.5-rc.1+build.10' - """ - return str(VersionInfo.parse(version).bump_build(token)) - - -@deprecated(version="2.10.0") -def finalize_version(version): - """ - Remove any prerelease and build metadata from the version string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.finalize_version` instead. - - .. versionadded:: 2.7.9 - Added :func:`finalize_version` - - :param version: version string - :return: the finalized version string - :rtype: str - - >>> semver.finalize_version('1.2.3-rc.5') - '1.2.3' - """ - verinfo = VersionInfo.parse(version) - return str(verinfo.finalize_version()) - - -@deprecated(version="2.10.0") -def replace(version, **parts): - """ - Replace one or more parts of a version and return the new string. - - .. deprecated:: 2.10.0 - Use :func:`semver.VersionInfo.replace` instead. - - .. versionadded:: 2.9.0 - Added :func:`replace` - - :param str version: the version string to replace - :param dict parts: the parts to be updated. Valid keys are: - ``major``, ``minor``, ``patch``, ``prerelease``, or ``build`` - :return: the replaced version string - :raises: TypeError, if ``parts`` contains invalid keys - :rtype: str - - >>> import semver - >>> semver.replace("1.2.3", major=2, patch=10) - '2.2.10' - """ - return str(VersionInfo.parse(version).replace(**parts)) - - -# ---- CLI -def cmd_bump(args): - """ - Subcommand: Bumps a version. - - Synopsis: bump - can be major, minor, patch, prerelease, or build - - :param args: The parsed arguments - :type args: :class:`argparse.Namespace` - :return: the new, bumped version - """ - maptable = { - "major": "bump_major", - "minor": "bump_minor", - "patch": "bump_patch", - "prerelease": "bump_prerelease", - "build": "bump_build", - } - if args.bump is None: - # When bump is called without arguments, - # print the help and exit - args.parser.parse_args(["bump", "-h"]) - - ver = VersionInfo.parse(args.version) - # get the respective method and call it - func = getattr(ver, maptable[args.bump]) - return str(func()) - - -def cmd_check(args): - """ - Subcommand: Checks if a string is a valid semver version. - - Synopsis: check - - :param args: The parsed arguments - :type args: :class:`argparse.Namespace` - """ - if VersionInfo.isvalid(args.version): - return None - raise ValueError("Invalid version %r" % args.version) - - -def cmd_compare(args): - """ - Subcommand: Compare two versions - - Synopsis: compare - - :param args: The parsed arguments - :type args: :class:`argparse.Namespace` - """ - return str(compare(args.version1, args.version2)) - - -def cmd_nextver(args): - """ - Subcommand: Determines the next version, taking prereleases into account. - - Synopsis: nextver - - :param args: The parsed arguments - :type args: :class:`argparse.Namespace` - """ - version = VersionInfo.parse(args.version) - return str(version.next_version(args.part)) - - -def createparser(): - """ - Create an :class:`argparse.ArgumentParser` instance. - - :return: parser instance - :rtype: :class:`argparse.ArgumentParser` - """ - parser = argparse.ArgumentParser(prog=__package__, description=__doc__) - - parser.add_argument( - "--version", action="version", version="%(prog)s " + __version__ - ) - - s = parser.add_subparsers() - # create compare subcommand - parser_compare = s.add_parser("compare", help="Compare two versions") - parser_compare.set_defaults(func=cmd_compare) - parser_compare.add_argument("version1", help="First version") - parser_compare.add_argument("version2", help="Second version") - - # create bump subcommand - parser_bump = s.add_parser("bump", help="Bumps a version") - parser_bump.set_defaults(func=cmd_bump) - sb = parser_bump.add_subparsers(title="Bump commands", dest="bump") - - # Create subparsers for the bump subparser: - for p in ( - sb.add_parser("major", help="Bump the major part of the version"), - sb.add_parser("minor", help="Bump the minor part of the version"), - sb.add_parser("patch", help="Bump the patch part of the version"), - sb.add_parser("prerelease", help="Bump the prerelease part of the version"), - sb.add_parser("build", help="Bump the build part of the version"), - ): - p.add_argument("version", help="Version to raise") - - # Create the check subcommand - parser_check = s.add_parser( - "check", help="Checks if a string is a valid semver version" - ) - parser_check.set_defaults(func=cmd_check) - parser_check.add_argument("version", help="Version to check") - - # Create the nextver subcommand - parser_nextver = s.add_parser( - "nextver", help="Determines the next version, taking prereleases into account." - ) - parser_nextver.set_defaults(func=cmd_nextver) - parser_nextver.add_argument("version", help="Version to raise") - parser_nextver.add_argument( - "part", help="One of 'major', 'minor', 'patch', or 'prerelease'" - ) - return parser - - -def process(args): - """ - Process the input from the CLI. - - :param args: The parsed arguments - :type args: :class:`argparse.Namespace` - :param parser: the parser instance - :type parser: :class:`argparse.ArgumentParser` - :return: result of the selected action - :rtype: str - """ - if not hasattr(args, "func"): - args.parser.print_help() - raise SystemExit() - - # Call the respective function object: - return args.func(args) - - -def main(cliargs=None): - """ - Entry point for the application script. - - :param list cliargs: Arguments to parse or None (=use :class:`sys.argv`) - :return: error code - :rtype: int - """ - try: - parser = createparser() - args = parser.parse_args(args=cliargs) - # Save parser instance: - args.parser = parser - result = process(args) - if result is not None: - print(result) - return 0 - - except (ValueError, TypeError) as err: - print("ERROR", err, file=sys.stderr) - return 2 - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/mods/DR/__init__.py b/mods/DR/__init__.py new file mode 100644 index 0000000..43badfc --- /dev/null +++ b/mods/DR/__init__.py @@ -0,0 +1,12 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" diff --git a/mods/DR/type_data.py b/mods/DR/type_data.py new file mode 100644 index 0000000..43badfc --- /dev/null +++ b/mods/DR/type_data.py @@ -0,0 +1,12 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie +# All rights reserved +# ------------------------------- + +""" +writen by shenjackyuanjie +mail: 3695888@qq.com +github: @shenjackyuanjie +gitee: @shenjackyuanjie +""" diff --git a/try/some_big_num.py b/try/some_big_num.py index fb6f5d4..3c38b27 100644 --- a/try/some_big_num.py +++ b/try/some_big_num.py @@ -11,18 +11,14 @@ github: @shenjackyuanjie gitee: @shenjackyuanjie """ import cProfile +import time def run(): - 一个很大的整数 = 11111111111111111111111111111111111111111111111 * 111111235111 - - 一个很大的浮点数 = 1111111111111111111111111111111111111111.1111111 * 11111123.5111 - print(一个很大的整数, '\n', 一个很大的浮点数) + start_time = time.perf_counter_ns() + print(*[x for x in range(1, 100000) if sum([int(i)**len(str(x)) for i in str(x)]) == x]) + print(time.perf_counter_ns() - start_time) -cProfile.run("run") +cProfile.run("run()") -""" -1234569279011111111111111111111111111111111111098765418321 - 1.234569279011111e+46 - """