日常生活的交流与学习

首页 新随笔 联系 管理

backup the current project

"""convert code to markdown
"""
import datetime
import os
import platform
import re
import shutil


class CodeToMarkDown:
    """_summary_"""

    __slots__ = ["path", "md_path", "code_file_path", "exclude_dirs", "exclude_files", "md_suffix_table", "include_exts", "key_work_filter_list"]

    def __init__(self, path: str = None) -> None:
        if path:
            self.path = path
        else:
            self.path = os.getcwd()
        # 需要排除的目录
        self.exclude_dirs = [
            "__pycache__",
            "venv",
            "build",
            "dist",
            "node_modules",
            "public",
            "LICENSE",
            "assets",
            "vendor",
            "tmp",
            "static",
            "templates",
            "bin",
            "obj",
            "Migrations",
            "Properties",
            "packages",
        ]
        # 排除的文件的后缀
        self.exclude_files = [
            "_NOTE.md",
            ".d.ts",
            ".lock",
            ".png",
            ".woff2",
            ".ttf",
            ".woff",
            ".css",
            "README.md",
            ".toml",
            "swagger-ui-bundle.js",
            "-lock.json",
            "zz_code2md.py",
            "zz.py",
            "temp.md",
        ]
        # 文件后缀名对应的 md code代码提示名
        self.md_suffix_table = {"command": "sh", "csproj": "xml"}
        # 需要包含的文件后缀名
        self.include_exts = [
            ".py",
            ".vue",
            ".js",
            ".ts",
            ".html",
            ".go",
            ".mod",
            ".json",
            ".txt",
            ".sh",
            ".command",
            ".cs",
            "csproj",
            ".jsx",
            ".sln",
            ".sh",
            ".bat",
        ]
        # 需要过滤的文件名的后缀
        self.key_work_filter_list = [""]

    def generate_md(self):
        self.__generate_md_file_path()
        self.__collect_code_files()
        self.__generate_md_file()

    def __generate_md_file_path(self):
        cur_time_str = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        md_name = f"Z_{cur_time_str}_NOTE.md"
        self.md_path = os.path.join(self.path, md_name)

    def __collect_code_files(self):
        """_summary_
        Returns:
            _type_: _description_
        """
        self.code_file_path = []
        for root, dirs, files in os.walk(self.path):
            # 过滤不符合的文件夹------------------------------------------------------------------------
            dirs[:] = [d for d in dirs if not d.startswith(".") and not any(ex in d for ex in self.exclude_dirs)]
            # 过滤不符合的文件-----------------------------------------------------------------------------
            files[:] = [f for f in files if not f.startswith(".") and not any(ex in f for ex in self.exclude_files)]
            # 筛选所有符合后缀的文件------------------------------------------------------------------------
            for file in files:
                # 正向过滤含有(\.py|vue|js|ts)$ 结尾的文件
                if any(file.endswith(ext) for ext in self.include_exts):
                    self.code_file_path.append(os.path.join(root, file))

    def __generate_md_file(self):
        for i, code_file_path in enumerate(self.code_file_path):
            print(i + 1, "->", self.__get_md_title_level_one(code_file_path))
            self.__readcode_writemd(code_file_path)

    def __get_md_title_level_one(self, code_file_path):
        """获取每个代码文件的md标题,去掉项目之前的文件路径
        Args:
            code_file_path (_type_): 代码路径
            project_path (_type_): 项目根路径
        Returns:
            _type_: 每个代码文件的md标题
        """
        # Get the common prefix of the two paths
        common_prefix = os.path.commonprefix([code_file_path, self.path])
        # Get the different parts of the two paths
        diff1 = code_file_path[len(common_prefix) + 1 :]
        md_title = os.path.join(os.path.basename(self.path), diff1)
        return md_title

    def __readcode_writemd(self, code_file_path):
        """_summary_
        Args:
            code_file_path (_type_): _description_
        """
        with open(code_file_path, "r", encoding="utf-8") as f:  # 打开文件
            try:
                content = f.read()
            except Exception as e:
                print(f"{code_file_path}{e}文件编码读取错误")
                content = ""
            self.__write2md(content, code_file_path)

    def __write2md(
        self,
        content,
        code_file_path,
    ):
        """_summary_
        Args:
            content (_type_): _description_
            suffix (_type_): _description_
            code_file_path (_type_): _description_
        """
        with open(self.md_path, "a", encoding="utf-8") as f:  # 打开文件
            md_title_level_one = self.__get_md_title_level_one(code_file_path)
            code_label = self.__get_code_md_lable_by_suffix(code_file_path)
            f.write("\n")
            f.write(f"# `{md_title_level_one}`\n\n")
            f.write(f"```{code_label}\n")
            f.write(content)
            f.write("\n")
            f.write("```\n\n\n")

    def __get_code_md_lable_by_suffix(self, code_file_path):
        suffix = re.findall(r'\.[^.\\/:*?"<>|\r\n]+$', code_file_path)
        if len(suffix):
            suffix = suffix[0][1:]
        if self.md_suffix_table.get(suffix) is not None:
            return self.md_suffix_table.get(suffix)
        return suffix


class MarkdownToCode:
    """_summary_
    Returns:
        _type_: _description_
    """

    __slots__ = ["path", "base_dir"]

    def __init__(self, path: str = None) -> None:
        if path:
            self.path = path
        else:
            self.path = self.__get_latest_md_file_path()

    def __get_latest_md_file_path(self):
        dst_md_files = []
        for root, _, files in os.walk(os.getcwd()):
            for file in files:
                if file.endswith("_NOTE.md"):
                    dst_md_files.append(os.path.join(root, file))

        return sorted(dst_md_files).pop()

    def generate_code(self):
        self.__set_base_dir()
        self.__read_md_file()

    def __read_md_file(self):
        """_summary_"""
        with open(self.path, "r", encoding="utf-8") as f:  # 打开文件
            md_text = f.read()
        # Match the first-level headings and code blocks
        # \n{1,}# `(.+)`\n{1,}```\w{2,5}\n{1,}
        pattern = r"^# `(.+)`\n{1,}```(?:\w{2,}\n)([\s\S]+?)\n{1,}```\n{1,}"
        matches = re.findall(pattern, md_text, re.MULTILINE)
        # Loop over the matches
        for i, (file_path, code) in enumerate(matches):
            print(f"{i}->", file_path)
            self.__create_from_file_path(file_path, code)

    def __set_base_dir(self):
        self.base_dir = os.path.dirname(self.path)

    def __create_from_file_path(self, file_path, content):
        """_summary_
        Args:
            file_path (_type_): _description_
            content (_type_): _description_
        """
        dir_path = os.path.join(self.base_dir, os.path.dirname(file_path))
        os.makedirs(dir_path, exist_ok=True)
        full_file_path = os.path.join(self.base_dir, file_path)
        with open(full_file_path, "w", encoding="utf-8") as f:
            f.write(content)


class CollectMarkdownNote:
    """_summary_"""

    __slots__ = [
        "path",
        "md_path",
        "cur_file_name",
        "cur_file_new_name",
        "md_files",
        "dotnet_md_files",
        "python_md_files",
        "dotnet_line_number_start",
        "dotnet_split_flag",
        "dotnet_file_names",
        "python_split_flag",
        "current_new_md_file_name",
        "save_md_file_heads",
        "split_flag",
        "other_split_flag",
        "other_md_files",
    ]

    def __init__(self, path: str = None) -> None:
        if path:
            self.path = path
        else:
            self.path = os.getcwd()

        self.dotnet_line_number_start = []

        self.dotnet_file_names = []
        self.current_new_md_file_name = None

        # 需要保留的markdown文件的开头
        # self.save_md_file_heads = ["zz_dotnet", "zz_python", "zz_csharp", "zz_note", "zz_"]
        self.save_md_file_heads = ["zz_"]
        # 需要需要的markdown文件,zz_开头,不在zz_note里面的markdown文件
        self.md_files = []
        #  需要收集的关于dotent的md文件,zz_开头,不在zz_note里面
        self.dotnet_md_files = []
        #  需要收集的关于python的md文件,zz_开头,不在zz_note里面
        self.python_md_files = []
        #  需要收集的关于python的md文件,zz_开头,不在zz_note里面
        self.other_md_files = []
        # 即将生成的python文件的文件名,就是当前文件的文件夹,加上时间戳的后缀
        self.cur_file_new_name = None
        # 当前这个python脚本的文件名
        self.cur_file_name = os.path.basename(__file__)

    def collect_markdown(self):
        """收集当前项目中的markdown笔记"""
        self.__get_new_python_file_name()
        self.__get_cur_markdown_notes()
        self.__read_cur_markdown_notes()
        self.__generate_new_python_file()

    def __write2md(self, line):
        # 如我文件名不为空,代表可以写入,同时要过滤到python中的注释符号,防止python脚本出现错误
        if (self.current_new_md_file_name is not None) and line != '"""\n' and line != '"""' and line != '\n"""':
            nf = open(self.current_new_md_file_name, "a+", encoding="utf-8")
            nf.write(line)
            nf.close()

    def un_collect_markdown(self):
        """doc"""
        f = open(self.cur_file_name, "r", encoding="utf-8")
        for i, line in enumerate(f):
            self.__write2md(line)
            res = re.findall(re.compile(r"^\"\"\"#==(.{1,10})=="), line)
            if len(res) > 0:
                self.current_new_md_file_name = self.__get_output_md_file_name_by_line(line)
                print(i + 1, "->", self.current_new_md_file_name, "start")
            if line.startswith('"""\n'):
                print(i + 1, "->", self.current_new_md_file_name, "end")
                self.current_new_md_file_name = None

    def __get_output_md_file_name_by_line(self, line):
        # 输出zz_note的子文件夹的名称,从"""==python==提取
        dir_name = "other"
        name = "other"
        pattern = re.compile(r"^\"\"\"#==(.{1,10})==(.+).md")
        res = pattern.match(line)
        if res:
            dir_name = res.groups()[0]
            name = res.groups()[1]

        # 生成markdown文件的后缀名,防止冲突
        cur_time_str = str(datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S"))
        # 生成的markdown文件的文件夹,zz_note/python,或者给zz_dotnet,取决于什么类型的文件
        dir_path = os.path.join("zz_note", dir_name)
        os.makedirs(dir_path, exist_ok=True)

        return "zz_note/" + dir_name + "/" + name + "_" + cur_time_str + ".md"

    def __read_cur_markdown_notes(self):
        """_summary_"""

        for md_file in self.md_files:
            if "dotnet" in md_file:
                self.dotnet_md_files.append(md_file)
            elif "python" in md_file:
                self.python_md_files.append(md_file)
            elif "other" in md_file:
                self.other_md_files.append(md_file)

    def __get_cur_markdown_notes(self):
        """_summary_"""
        print("开始收集,所以以zz_开头的,不在zz_note文件夹中的markdown文件")
        pattern = re.compile(r"zz_(\w+)_")

        for root, dirs, files in os.walk(self.path):
            dirs[:] = [d for d in dirs if "zz_note" not in d]
            # 过滤符合的文件-----------------------------------------------------------------------------
            files[:] = [f for f in files if not f.startswith(".") and any(ex in f for ex in [".md"])]
            # 筛选所有符合后缀的文件------------------------------------------------------------------------
            for i, file in enumerate(files):
                print(i + 1, "->", file)
                res = pattern.findall(file)
                if len(res) > 0:
                    self.md_files.append(os.path.join(root, file))

    def __get_new_python_file_name(self):
        cur_time_str = str(datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S"))
        file_names = self.cur_file_name.split("_")
        if len(file_names) > 1:
            self.cur_file_new_name = f"{os.path.splitext(file_names[0])[0]}_{cur_time_str}.py"
        else:
            self.cur_file_new_name = f"{os.path.splitext(self.cur_file_name)[0]}_{cur_time_str}.py"

    def __get_cur_file_name(self, md_file_path):
        return os.path.basename(md_file_path)

    def __generate_new_python_file(self):
        """_summary_"""
        f = open(self.cur_file_name, "r", encoding="utf-8")
        for line in f:
            nf = open(self.cur_file_new_name, "a+", encoding="utf-8")
            nf.write(line)

        for md_file in self.md_files:
            split_flag = "other"
            pattern = re.compile(r"zz_(\w+)_")
            res = pattern.findall(md_file)
            if len(res) > 0:
                split_flag = res[0]

            md_title = self.__get_cur_file_name(md_file)
            content = self.__read_md_file(md_file)
            nf.write(f'\n\n"""#=={split_flag}=={md_title}\n\n')
            nf.write(self.__filter_python_comment(content))
            nf.write('\n"""\n\n')

        f.close()
        nf.close()
        # 备份新生成的python文件
        self.__copy_current_python_file_to_dst_dir(self.cur_file_new_name)

    def __copy_current_python_file_to_dst_dir(self, current_python_file_name):
        """备份新生成的python文件,到特定的文件夹

        Args:
            current_python_file_name (_type_): _description_
        """
        system = platform.system()
        if system == "Windows":
            dir_path = r"D:/zz"
            os.makedirs(dir_path, exist_ok=True)
            shutil.copy(current_python_file_name, os.path.join(dir_path, current_python_file_name))
        elif system == "Darwin":
            dir_path = r"/Users/song/Code/zz_note"
            os.makedirs(dir_path, exist_ok=True)
            shutil.copy(current_python_file_name, os.path.join(dir_path, current_python_file_name))
        else:
            print("Unknown system")

    def __filter_python_comment(self, content: str):
        return content.replace('"""', "")

    def __read_md_file(self, file):
        with open(file, "r", encoding="utf-8") as f:
            content = f.read()
            return content


def backup_current_project():
    """_summary_"""
    src_dir = os.path.dirname(__file__)
    cur_time_str = str(datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
    compress_filename = f"{os.path.basename(src_dir)}_{cur_time_str}"
    dst_dir = os.path.join(
        os.path.dirname(os.path.dirname(__file__)),
        compress_filename,
    )
    shutil.copytree(src_dir, dst_dir)


if __name__ == "__main__":
    print("===============================start===============================")
    print("1. Project Convert to Markdown 2. Markdown Convert to Project")
    print("3. Collect Markdown Notes      4. Uncollect Markdown Notes")
    print("5. Backup the project      ")
    try:
        option_number = int(input("Please input a number: "))
    except Exception as e:
        option_number = 0
    print("您输入的整数是:", option_number)
    if option_number == 1:
        code2md = CodeToMarkDown()
        code2md.generate_md()
    elif option_number == 2:
        md_path = input("请输入需要转换的markdown文件路径(默认使用当前路径最新的markdown文件) : ")
        md2code = MarkdownToCode(md_path)
        md2code.generate_code()
    elif option_number == 3:
        collect_md = CollectMarkdownNote()
        collect_md.collect_markdown()
    elif option_number == 4:
        is_del = input("是否要删除现有的文件夹(Y/N):")
        if is_del == "N" or is_del == "n":
            pass
        else:
            try:
                res = shutil.rmtree("zz_note")
                print("zz_note文件夹,删除成功")
            except FileNotFoundError as e:
                print("no such directory,zz_note")
        collect_md = CollectMarkdownNote()
        collect_md.un_collect_markdown()
    elif option_number == 5:
        backup_current_project()
    else:
        print("unknown option")
    print("===============================done===============================")

# ================================================================================================


"""#==python==zz_python_的vscode配置.md


# `.vscode/.Pylintrc`

```sh
# This Pylint rcfile contains a best-effort configuration to uphold the
# best-practices and style described in the Google Python style guide:
#   https://google.github.io/styleguide/pyguide.html
#
# Its canonical open-source location is:
#   https://google.github.io/styleguide/pylintrc

[MASTER]

# Files or directories to be skipped. They should be base names, not paths.
ignore=third_party

# Files or directories matching the regex patterns are skipped. The regex
# matches against base names, not paths.
ignore-patterns=

# Pickle collected data for later comparisons.
persistent=no

# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=

# Use multiple processes to speed up Pylint.
jobs=4

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no


[MESSAGES CONTROL]

# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
#enable=

# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=abstract-method,
        broad-exception-caught,
        missing-module-docstring,
        apply-builtin,
        arguments-differ,
        attribute-defined-outside-init,
        backtick,
        bad-option-value,
        basestring-builtin,
        buffer-builtin,
        c-extension-no-member,
        consider-using-enumerate,
        cmp-builtin,
        cmp-method,
        coerce-builtin,
        coerce-method,
        delslice-method,
        div-method,
        duplicate-code,
        eq-without-hash,
        execfile-builtin,
        file-builtin,
        filter-builtin-not-iterating,
        fixme,
        getslice-method,
        global-statement,
        hex-method,
        idiv-method,
        implicit-str-concat,
        import-error,
        import-self,
        import-star-module-level,
        inconsistent-return-statements,
        input-builtin,
        intern-builtin,
        invalid-str-codec,
        locally-disabled,
        long-builtin,
        long-suffix,
        map-builtin-not-iterating,
        misplaced-comparison-constant,
        metaclass-assignment,
        next-method-called,
        next-method-defined,
        no-absolute-import,
        no-else-break,
        no-else-continue,
        no-else-raise,
        no-else-return,
        no-init,  # added
        no-member,
        no-name-in-module,
        no-self-use,
        nonzero-method,
        oct-method,
        old-division,
        old-ne-operator,
        old-octal-literal,
        old-raise-syntax,
        parameter-unpacking,
        print-statement,
        raising-string,
        range-builtin-not-iterating,
        raw_input-builtin,
        rdiv-method,
        reduce-builtin,
        relative-import,
        reload-builtin,
        round-builtin,
        setslice-method,
        signature-differs,
        standarderror-builtin,
        suppressed-message,
        sys-max-int,
        too-few-public-methods,
        too-many-ancestors,
        too-many-arguments,
        too-many-boolean-expressions,
        too-many-branches,
        too-many-instance-attributes,
        too-many-locals,
        too-many-nested-blocks,
        too-many-public-methods,
        too-many-return-statements,
        too-many-statements,
        trailing-newlines,
        unichr-builtin,
        unicode-builtin,
        unnecessary-pass,
        unpacking-in-except,
        useless-else-on-loop,
        useless-object-inheritance,
        useless-suppression,
        using-cmp-argument,
        wrong-import-order,
        xrange-builtin,
        zip-builtin-not-iterating,




[REPORTS]

# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text

# Tells whether to display a full report or only the messages
reports=no

# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)

# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=


[BASIC]

# Good variable names which should always be accepted, separated by a comma
good-names=main,_

# Bad variable names which should always be refused, separated by a comma
bad-names=

# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=

# Include a hint for the correct naming format with invalid-name
include-naming-hint=no

# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl

# Regular expression matching correct function names
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$

# Regular expression matching correct variable names
variable-rgx=^[a-z][a-z0-9_]*$

# Regular expression matching correct constant names
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$

# Regular expression matching correct attribute names
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$

# Regular expression matching correct argument names
argument-rgx=^[a-z][a-z0-9_]*$

# Regular expression matching correct class attribute names
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$

# Regular expression matching correct inline iteration names
inlinevar-rgx=^[a-z][a-z0-9_]*$

# Regular expression matching correct class names
class-rgx=^_?[A-Z][a-zA-Z0-9]*$

# Regular expression matching correct module names
module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$

# Regular expression matching correct method names
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$

# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$

# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=10


[TYPECHECK]

# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager

# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes

# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=

# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local

# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=


[FORMAT]

# Maximum number of characters on a single line.
max-line-length=150

# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
# lines made too long by directives to pytype.

# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=(?x)(
  ^\s*(\#\ )?<?https?://\S+>?$|
  ^\s*(from\s+\S+\s+)?import\s+.+$)

# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=yes

# Maximum number of lines in a module
max-module-lines=99999

# String used as indentation unit.  The internal Google style guide mandates 2
# spaces.  Google's externaly-published style guide says 4, consistent with
# PEP 8.  Here, we use 2 spaces, for conformity with many open-sourced Google
# projects (like TensorFlow).
indent-string='    '

# Number of spaces of indent required inside a hanging  or continued line.
indent-after-paren=4

# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=


[MISCELLANEOUS]

# List of note tags to take in consideration, separated by a comma.
notes=TODO


[STRING]

# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=yes


[VARIABLES]

# Tells whether we should check for unused import in __init__ files.
init-import=no

# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)

# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=

# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb

# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools


[LOGGING]

# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging,absl.logging,tensorflow.io.logging


[SIMILARITIES]

# Minimum lines number of a similarity.
min-similarity-lines=4

# Ignore comments when computing similarities.
ignore-comments=yes

# Ignore docstrings when computing similarities.
ignore-docstrings=yes

# Ignore imports when computing similarities.
ignore-imports=no


[SPELLING]

# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=

# List of comma separated words that should not be checked.
spelling-ignore-words=

# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=

# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no


[IMPORTS]

# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,
                   TERMIOS,
                   Bastion,
                   rexec,
                   sets

# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=

# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=

# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=

# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=

# Force import order to recognize a module as part of a third party library.
known-third-party=enchant, absl

# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no


[CLASSES]

# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
                      __new__,
                      setUp

# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
                  _fields,
                  _replace,
                  _source,
                  _make

# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls,
                            class_

# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs


[EXCEPTIONS]

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=builtins.StandardError,
                       builtins.Exception,
                       builtins.BaseException

.vscode/settings.json


{
  "python.analysis.autoImportCompletions": true,
  // 若要为安装在非标准位置的包启用 IntelliSense,请将这些位置添加到 settings.json 文件中的 python.analysis.extraPaths 集合中(默认集合为空)。
  // 例如,您可能已将 Google App Engine 安装在自定义位置,在本例中,请按如下方式指定这些位置:
  // "python.analysis.extraPaths": [
  //     "C:/Program Files (x86)/Google/google_appengine",
  //     "C:/Program Files (x86)/Google/google_appengine/lib/flask-0.12"]

  // "python.analysis.extraPaths": [],
  "python.analysis.packageIndexDepths": [
    {
      "name": "fastapi",
      "depth": 2
    },
    {
      "name": "selenium",
      "depth": 2,
      "includeAllSymbols": false
    }
  ],

  // "pylint.path": ["${workspaceFolder}/.venv/bin", "-m", "pylint"],
  // pylint的配置
  "pylint.args": ["--rcfile=${workspaceFolder}/.vscode/.pylintrc"],
  "[python]": {
    "diffEditor.ignoreTrimWhitespace": false,
    "editor.formatOnType": true,
    "editor.formatOnSave": true,
    "editor.formatOnPaste": true,
    "editor.wordBasedSuggestions": "off",
    // "editor.defaultFormatter": "ms-python.pylint",
    "editor.defaultFormatter": "ms-python.black-formatter",
    "editor.codeActionsOnSave": {
      "source.organizeImports": "explicit"
    }
  },
  "black-formatter.args": ["--line-length=150"],
  "editor.tabSize": 2,
  "isort.args": [
    "--profile",
    "black"
  ],
  "dotnet.defaultSolution": "dotnet_agv_back.sln"
}

"""

"""#pythonzz_python_运行脚本bat_shell脚本.md

bat脚本传递文件路径给python脚本

简单版本

@echo off
:start
set filePath=
set /p filePath=Please input file path:
python main.py  %filePath%
goto start

指定python的版本(Python虚拟环境)

@echo off
:start
set filePath=
set /p filePath=Please input file path:
D:\Python38\python E:\song\python_code2md\md2code\md2code.py  %filePath%
goto start

shell脚本运行python(mac系统)

#! /bin/bash
# 激活虚拟环境,安装目前的情况,不需要虚拟环境,也可以实现
# source /home/song/venv/bin/activate
echo "请拖入一个代码项目根目录的文件或者文件夹:"
read file
python3 /Users/song/Code/script_python/code2md/md2code.py "$file"
# 等待五秒钟,然后自动关闭
sleep 3 
osascript -e 'tell application "Terminal" to close first window' & exit

"""

"""#pythonzz_python_的gitignore文件.md

.gitignore

### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

"""

"""#dotnetzz_dotnet_ef工具使用.md

EF Core

# 为模型的更改添加一个新的迁移
dotnet ef migrations add <NAME>
#  删除上一个迁移
dotnet ef migrations remove
#  列出所有的迁移
dotnet ef migrations list
#  生成一个SQL脚本,用于将数据库更新到指定的迁移
dotnet ef migrations script
#  将数据库更新到指定的迁移或最新的迁移
dotnet ef database update
#  删除数据库
dotnet ef database drop
#  从现有数据库生成模型
dotnet ef dbcontext scaffold <CONNECTION> <PROVIDER>
#  获取当前的DbContext的信息
dotnet ef dbcontext info
#  列出项目中的所有DbContext
dotnet ef dbcontext list

"""

"""#dotnetzz_dotnet_升级助手.md

.NET 升级助手

安装并运行升级助手

dotnet tool install -g upgrade-assistant

升级项目

upgrade-assistant upgrade <Path to Project>

"""

"""#dotnetzz_dotnet_的依赖注入.md

原先的模式

GamesEndpoints.cs

public static class GamesEndpoints
{
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {
        // 自动创建一个实例,然后使用
        InMemGamesRepository repository = new();
        var group = endpoints.MapGroup("/games").WithParameterValidation();
        group.MapGet("/", () => repository.GetAll());
        return group;
    }
}

InMemGamesRepository.cs

using GameStore.Api.Entities;
namespace GameStore.Api.Repositoriesa;

public class InMemGamesRepository 
{
    private readonly List<Game> games = new()
    {
        new Game(){
            Id = 1,
            Name="Street Fighter II",
            Genre ="Fighting",
            Price = 19.99M,
            ReleaseDate = new DateTime(1991,2,1),
            ImgUri = "https://palcehold.co/100"
        },
        new Game(){
            Id = 2,
            Name="FIFA 23",
            Genre ="Sports",
            Price = 29.99M,
            ReleaseDate = new DateTime(2022,2,1),
            ImgUri = "https://palcehold.co/100"
        },

};

    public IEnumerable<Game> GetAll()
    {
        return games;
    }
    public Game? Get(int id)
    {
        return games.Find(game => game.Id == id);
    }
    public void Create(Game game)
    {
        game.Id = games.Max(game => game.Id) + 1;
        games.Add(game);
    }
    public void Update(Game updatedGame)
    {
        var index = games.FindIndex(game => game.Id == updatedGame.Id);
        games[index] = updatedGame;
    }
    public void Delete(int id)
    {
        var index = games.FindIndex(game => game.Id == id);
        games.RemoveAt(index);
    }

}

现在的模式

GamesEndpoints.cs


using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
using GameStore.Api.Entities;
using GameStore.Api.Repositoriesa;

namespace GameStore.Api.Endpoints;

public static class GamesEndpoints
{

    const string GetGameEndpointName = "GetGame";
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {

        var group = endpoints.MapGroup("/games").WithParameterValidation();

        // 直接依赖注入
        group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

        group.MapGet("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get(id);
            if (game is null)
            {
                return Results.NotFound();
            }
            return Results.Ok(game);
        }).WithName(GetGameEndpointName);

        group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) =>
        {

            Game? existingGame = repository.Get(id);
            if (existingGame is null)
            {
                return Results.NotFound();
            }
            existingGame.Name = updatedGame.Name;
            existingGame.Genre = updatedGame.Genre;
            existingGame.Price = updatedGame.Price;
            existingGame.ReleaseDate = updatedGame.ReleaseDate;
            existingGame.ImgUri = updatedGame.ImgUri;

            repository.Update(existingGame);

            return Results.NoContent();
        });

        group.MapDelete("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get (id);
            if (game is not null)
            {
                repository.Delete(id);
            }
            return Results.NoContent();
        });


        return group;

    }

}

对比

手动实例化

InMemGamesRepository repository = new();
group.MapGet("/", () => repository.GetAll());

依赖注入

依赖注入:

group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>();
// builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();

"""

"""#dotnetzz_dotnet_接口的扩展方法.md

接口的扩展方法

定义

当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。

接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。

例子

假设我们有一个接口 IVehicle,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。

public interface IVehicle
{
    int MilesDriven { get; set; }
}

public static class Extensions
{
    // 这是一个接口的扩展方法
    public static int FeetDriven(this IVehicle vehicle)
    {
        // 假设1英里等于5028英尺
        return vehicle.MilesDriven * 5028;
    }
}

class Program
{
    static void Main()
    {
        // 创建一个实现了 IVehicle 接口的类
        var car = new Car { MilesDriven = 100 };

        // 调用扩展方法
        int feet = car.FeetDriven();
        Console.WriteLine($"Car has driven {feet} feet.");
    }
}

public class Car : IVehicle
{
    public int MilesDriven { get; set; }
}

在上面的代码中,我们定义了一个接口 IVehicle,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven,它可以在任何实现了 IVehicle 接口的类上调用。在 Main 方法中,我们创建了一个 Car 类的实例,并调用了扩展方法来计算行驶的英尺数。

总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。

this关键字

在C#中,this 关键字用于引用当前对象的实例。在接口的扩展方法中,this 关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。

让我详细解释一下:

  • 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用 this 关键字,指示我们要扩展的类型。
  • 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
  • this 关键字告诉编译器将当前实例作为第一个参数传递给这个方法。

例如,如果我们有一个接口 IVehicle 表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle 表示我们要在实现了 IVehicle 接口的类的实例上调用这个方法。

"""

"""#dotnetzz_dotnet_eftool指定文件夹.md

ef core 生成迁移文件时,如何指定文件夹

dotnet ef migrations add InitialCreate --output-dir Data/Migrations                  
dotnet ef database update         

"""

"""#dotnetzz_dotnet_的依赖注入.md

原先的模式

GamesEndpoints.cs

public static class GamesEndpoints
{
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {
        // 自动创建一个实例,然后使用
        InMemGamesRepository repository = new();
        var group = endpoints.MapGroup("/games").WithParameterValidation();
        group.MapGet("/", () => repository.GetAll());
        return group;
    }
}

InMemGamesRepository.cs

using GameStore.Api.Entities;
namespace GameStore.Api.Repositoriesa;

public class InMemGamesRepository 
{
    private readonly List<Game> games = new()
    {
        new Game(){
            Id = 1,
            Name="Street Fighter II",
            Genre ="Fighting",
            Price = 19.99M,
            ReleaseDate = new DateTime(1991,2,1),
            ImgUri = "https://palcehold.co/100"
        },
        new Game(){
            Id = 2,
            Name="FIFA 23",
            Genre ="Sports",
            Price = 29.99M,
            ReleaseDate = new DateTime(2022,2,1),
            ImgUri = "https://palcehold.co/100"
        },

};

    public IEnumerable<Game> GetAll()
    {
        return games;
    }
    public Game? Get(int id)
    {
        return games.Find(game => game.Id == id);
    }
    public void Create(Game game)
    {
        game.Id = games.Max(game => game.Id) + 1;
        games.Add(game);
    }
    public void Update(Game updatedGame)
    {
        var index = games.FindIndex(game => game.Id == updatedGame.Id);
        games[index] = updatedGame;
    }
    public void Delete(int id)
    {
        var index = games.FindIndex(game => game.Id == id);
        games.RemoveAt(index);
    }

}

现在的模式

GamesEndpoints.cs


using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
using GameStore.Api.Entities;
using GameStore.Api.Repositoriesa;

namespace GameStore.Api.Endpoints;

public static class GamesEndpoints
{

    const string GetGameEndpointName = "GetGame";
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {

        var group = endpoints.MapGroup("/games").WithParameterValidation();

        // 直接依赖注入
        group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

        group.MapGet("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get(id);
            if (game is null)
            {
                return Results.NotFound();
            }
            return Results.Ok(game);
        }).WithName(GetGameEndpointName);

        group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) =>
        {

            Game? existingGame = repository.Get(id);
            if (existingGame is null)
            {
                return Results.NotFound();
            }
            existingGame.Name = updatedGame.Name;
            existingGame.Genre = updatedGame.Genre;
            existingGame.Price = updatedGame.Price;
            existingGame.ReleaseDate = updatedGame.ReleaseDate;
            existingGame.ImgUri = updatedGame.ImgUri;

            repository.Update(existingGame);

            return Results.NoContent();
        });

        group.MapDelete("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get (id);
            if (game is not null)
            {
                repository.Delete(id);
            }
            return Results.NoContent();
        });


        return group;

    }

}

对比

手动实例化

InMemGamesRepository repository = new();
group.MapGet("/", () => repository.GetAll());

依赖注入

依赖注入:

group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>();
// builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();

"""

"""#dotnetzz_dotnet_接口的扩展方法.md

接口的扩展方法

定义

当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。

接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。

例子

假设我们有一个接口 IVehicle,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。

public interface IVehicle
{
    int MilesDriven { get; set; }
}

public static class Extensions
{
    // 这是一个接口的扩展方法
    public static int FeetDriven(this IVehicle vehicle)
    {
        // 假设1英里等于5028英尺
        return vehicle.MilesDriven * 5028;
    }
}

class Program
{
    static void Main()
    {
        // 创建一个实现了 IVehicle 接口的类
        var car = new Car { MilesDriven = 100 };

        // 调用扩展方法
        int feet = car.FeetDriven();
        Console.WriteLine($"Car has driven {feet} feet.");
    }
}

public class Car : IVehicle
{
    public int MilesDriven { get; set; }
}

在上面的代码中,我们定义了一个接口 IVehicle,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven,它可以在任何实现了 IVehicle 接口的类上调用。在 Main 方法中,我们创建了一个 Car 类的实例,并调用了扩展方法来计算行驶的英尺数。

总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。

this关键字

在C#中,this 关键字用于引用当前对象的实例。在接口的扩展方法中,this 关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。

让我详细解释一下:

  • 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用 this 关键字,指示我们要扩展的类型。
  • 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
  • this 关键字告诉编译器将当前实例作为第一个参数传递给这个方法。

例如,如果我们有一个接口 IVehicle 表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle 表示我们要在实现了 IVehicle 接口的类的实例上调用这个方法。

"""

"""#dotnetzz_dotnet_eftool指定文件夹.md

ef core 生成迁移文件时,如何指定文件夹

dotnet ef migrations add InitialCreate --output-dir Data/Migrations                  
dotnet ef database update         

"""

"""#otherzz_other_vscode插件restclient的使用.md

vscode插件中restclient插件的使用

1.讲下面的文件保存 xxx.http 的格式的文件

### get

GET http://localhost:5090/games HTTP/1.1


### get by id

GET http://localhost:5090/games/1 HTTP/1.1



### post

POST http://localhost:5090/games HTTP/1.1
content-type: application/json

{
    "name": "Hun Dou Luo2222222",
    "genre": "Fighting",
    "price": 19.99,
    "releaseDate": "1992-02-01T00:00:00",
    "imageUri": "https://palcehold.co/100"
}

### post missing name

POST http://localhost:5090/games HTTP/1.1
content-type: application/json

{
    "genre": "Fighting",
    "price": 19.99,
    "releaseDate": "1992-02-01T00:00:00",
    "imageUri": "https://palcehold.co/100"
}

"""

"""#pythonzz_python_正则表达式.md

正则表达式在线测试网站

regexr

https://regexr.com/

分组匹配

import re
name = "#==other==zz_other_vscode插件restclient的使用.md"
pattern = re.compile(r'#==(.{1,10})==(.+).md')
res =pattern.match(name)
if res:
    print(res.groups())   # => ('other', 'zz_other_vscode插件restclient的使用')
    print(res.groups()[0])# => other
    print(res.groups()[1])# => zz_other_vscode插件restclient的使用

正则表达式中各个函数的区别

re.match

  • re.match(pattern, string):这个函数用于检查字符串的开头是否匹配给定的模式,如果匹配,返回一个匹配对象,否则返回None。这个函数只在字符串的开头进行匹配,不会在字符串的其他位置查找模式。例如:
import re
result = re.match(r"hello", "hello world")
print(result) # <re.Match object; span=(0, 5), match='hello'>
result = re.match(r"world", "hello world")
print(result) # None

re.search

  • re.search(pattern, string):这个函数用于在字符串中查找给定的模式的第一个匹配,如果找到,返回一个匹配对象,否则返回None。这个函数会在字符串的任何位置进行匹配,不仅仅是开头。例如:
import re
result = re.search(r"hello", "hello world")
print(result) # <re.Match object; span=(0, 5), match='hello'>
result = re.search(r"world", "hello world")
print(result) # <re.Match object; span=(6, 11), match='world'>

re.findall

  • re.findall(pattern, string):这个函数用于在字符串中查找给定的模式的所有匹配,返回一个包含所有匹配的字符串的列表,如果没有找到匹配,返回一个空列表。这个函数会在字符串的任何位置进行匹配,不会停止在第一个匹配。例如:
import re
result = re.findall(r"hello", "hello world hello python")
print(result) # ['hello', 'hello']
result = re.findall(r"world", "hello world hello python")
print(result) # ['world']

re.finditer

  • re.finditer(pattern, string):这个函数用于在字符串中查找给定的模式的所有匹配,返回一个包含所有匹配对象的迭代器,如果没有找到匹配,返回一个空的迭代器。这个函数会在字符串的任何位置进行匹配,不会停止在第一个匹配。这个函数与re.findall的区别是,它返回的是匹配对象,而不是字符串,这样可以获取更多的匹配信息,如位置,分组等。例如:
import re
result = re.finditer(r"hello", "hello world hello python")
for match in result:
    print(match) # <re.Match object; span=(0, 5), match='hello'>
                 # <re.Match object; span=(12, 17), match='hello'>
result = re.finditer(r"world", "hello world hello python")
for match in result:
    print(match) # <re.Match object; span=(6, 11), match='world'>

re.sub

  • re.sub(pattern, repl, string):这个函数用于在字符串中替换给定的模式的所有匹配,返回一个新的字符串,其中所有的匹配都被repl替换,如果没有找到匹配,返回原始字符串。repl可以是一个字符串,也可以是一个函数,用于根据匹配对象生成替换的字符串。例如:
import re
result = re.sub(r"hello", "hi", "hello world hello python")
print(result) # hi world hi python
result = re.sub(r"(\w+) (\w+)", r"\2 \1", "hello world hello python")
print(result) # world hello python hello

re.split

  • re.split(pattern, string):这个函数用于用给定的模式作为分隔符,将字符串分割成多个子字符串,返回一个包含所有子字符串的列表,如果没有找到匹配,返回一个只包含原始字符串的列表。例如:
import re
result = re.split(r"\s", "hello world hello python")
print(result) # ['hello', 'world', 'hello', 'python']
result = re.split(r"o", "hello world hello python")
print(result) # ['hell', ' w', 'rld hell', ' pyth', 'n']

"""

"""#dotnetzz_dotnet_的依赖注入.md

原先的模式

GamesEndpoints.cs

public static class GamesEndpoints
{
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {
        // 自动创建一个实例,然后使用
        InMemGamesRepository repository = new();
        var group = endpoints.MapGroup("/games").WithParameterValidation();
        group.MapGet("/", () => repository.GetAll());
        return group;
    }
}

InMemGamesRepository.cs

using GameStore.Api.Entities;
namespace GameStore.Api.Repositoriesa;

public class InMemGamesRepository 
{
    private readonly List<Game> games = new()
    {
        new Game(){
            Id = 1,
            Name="Street Fighter II",
            Genre ="Fighting",
            Price = 19.99M,
            ReleaseDate = new DateTime(1991,2,1),
            ImgUri = "https://palcehold.co/100"
        },
        new Game(){
            Id = 2,
            Name="FIFA 23",
            Genre ="Sports",
            Price = 29.99M,
            ReleaseDate = new DateTime(2022,2,1),
            ImgUri = "https://palcehold.co/100"
        },

};

    public IEnumerable<Game> GetAll()
    {
        return games;
    }
    public Game? Get(int id)
    {
        return games.Find(game => game.Id == id);
    }
    public void Create(Game game)
    {
        game.Id = games.Max(game => game.Id) + 1;
        games.Add(game);
    }
    public void Update(Game updatedGame)
    {
        var index = games.FindIndex(game => game.Id == updatedGame.Id);
        games[index] = updatedGame;
    }
    public void Delete(int id)
    {
        var index = games.FindIndex(game => game.Id == id);
        games.RemoveAt(index);
    }

}

现在的模式

GamesEndpoints.cs


using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
using GameStore.Api.Entities;
using GameStore.Api.Repositoriesa;

namespace GameStore.Api.Endpoints;

public static class GamesEndpoints
{

    const string GetGameEndpointName = "GetGame";
    public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints)
    {

        var group = endpoints.MapGroup("/games").WithParameterValidation();

        // 直接依赖注入
        group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

        group.MapGet("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get(id);
            if (game is null)
            {
                return Results.NotFound();
            }
            return Results.Ok(game);
        }).WithName(GetGameEndpointName);

        group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) =>
        {

            Game? existingGame = repository.Get(id);
            if (existingGame is null)
            {
                return Results.NotFound();
            }
            existingGame.Name = updatedGame.Name;
            existingGame.Genre = updatedGame.Genre;
            existingGame.Price = updatedGame.Price;
            existingGame.ReleaseDate = updatedGame.ReleaseDate;
            existingGame.ImgUri = updatedGame.ImgUri;

            repository.Update(existingGame);

            return Results.NoContent();
        });

        group.MapDelete("/{id}", (IGamesRepository repository,int id) =>
        {
            Game? game = repository.Get (id);
            if (game is not null)
            {
                repository.Delete(id);
            }
            return Results.NoContent();
        });


        return group;

    }

}

对比

手动实例化

InMemGamesRepository repository = new();
group.MapGet("/", () => repository.GetAll());

依赖注入

依赖注入:

group.MapGet("/", (IGamesRepository repository) => repository.GetAll());

注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>();
// builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();

"""

"""#dotnetzz_dotnet_接口的扩展方法.md

接口的扩展方法

定义

当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。

接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。

例子

假设我们有一个接口 IVehicle,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。

public interface IVehicle
{
    int MilesDriven { get; set; }
}

public static class Extensions
{
    // 这是一个接口的扩展方法
    public static int FeetDriven(this IVehicle vehicle)
    {
        // 假设1英里等于5028英尺
        return vehicle.MilesDriven * 5028;
    }
}

class Program
{
    static void Main()
    {
        // 创建一个实现了 IVehicle 接口的类
        var car = new Car { MilesDriven = 100 };

        // 调用扩展方法
        int feet = car.FeetDriven();
        Console.WriteLine($"Car has driven {feet} feet.");
    }
}

public class Car : IVehicle
{
    public int MilesDriven { get; set; }
}

在上面的代码中,我们定义了一个接口 IVehicle,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven,它可以在任何实现了 IVehicle 接口的类上调用。在 Main 方法中,我们创建了一个 Car 类的实例,并调用了扩展方法来计算行驶的英尺数。

总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。

this关键字

在C#中,this 关键字用于引用当前对象的实例。在接口的扩展方法中,this 关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。

让我详细解释一下:

  • 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用 this 关键字,指示我们要扩展的类型。
  • 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
  • this 关键字告诉编译器将当前实例作为第一个参数传递给这个方法。

例如,如果我们有一个接口 IVehicle 表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle 表示我们要在实现了 IVehicle 接口的类的实例上调用这个方法。

"""

"""#dotnetzz_dotnet_eftool指定文件夹.md

ef core 生成迁移文件时,如何指定文件夹

dotnet ef migrations add InitialCreate --output-dir Data/Migrations                  
dotnet ef database update         

"""

"""#otherzz_other_vscode插件restclient的使用.md

vscode插件中restclient插件的使用

1.讲下面的文件保存 xxx.http 的格式的文件

### get

GET http://localhost:5090/games HTTP/1.1


### get by id

GET http://localhost:5090/games/1 HTTP/1.1



### post

POST http://localhost:5090/games HTTP/1.1
content-type: application/json

{
    "name": "Hun Dou Luo2222222",
    "genre": "Fighting",
    "price": 19.99,
    "releaseDate": "1992-02-01T00:00:00",
    "imageUri": "https://palcehold.co/100"
}

### post missing name

POST http://localhost:5090/games HTTP/1.1
content-type: application/json

{
    "genre": "Fighting",
    "price": 19.99,
    "releaseDate": "1992-02-01T00:00:00",
    "imageUri": "https://palcehold.co/100"
}
posted on 2024-01-20 22:53  lazycookie  阅读(20)  评论(0编辑  收藏  举报