forked from wyf9/sleepy
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
398 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
__pycache__/ | ||
data.json | ||
data.json | ||
data.old.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Builder script | ||
project_manifest.json | ||
build.py | ||
|
||
# __pycache__ folder | ||
**/__pycache__ | ||
|
||
# Tools for docs | ||
compile_docs.py | ||
**/docs_templates | ||
|
||
# Test files | ||
test.py | ||
test.json | ||
test.jsonc | ||
|
||
# Distribution folders | ||
/build | ||
/dist | ||
/*.egg-info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 NJickolai Beloguzov | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
本文件夹中的内容来自 [kobayashi-deepinsight/jsonc-parser](https://github.com/kobayashi-deepinsight/jsonc-parser) | ||
|
||
> 以下为原文件内容 | ||
# jsonc-parser | ||
|
||
This package is a lightweight, zero-dependency module for parsing files with .jsonc extension. (<i>a.k.a. JSON with comments</i>) | ||
|
||
## Installation | ||
|
||
To install this package, simply download it from [PyPI](https://pypi.org/project/jsonc-parser): | ||
|
||
pip install jsonc-parser | ||
|
||
Also you can build it yourself from source code available on [GitHub](https://github.com/NickolaiBeloguzov/jsonc-parser) | ||
|
||
## Usage | ||
|
||
You need to just import _JsoncParser_ class from this package: | ||
|
||
from jsonc_parser.parser import JsoncParser | ||
|
||
This class requires no instance to function (i.e. it is fully static) | ||
|
||
## Functions | ||
|
||
These are all methods that JsoncParser class provides for working with .jsonc files: | ||
|
||
- ##### JsoncParser.parse_file(filepath: PathLike) -> dict | ||
|
||
This function parses file, specified in _filepath_ parameter, and deserializes it into a valid Python object (dictionary), removing any comment in the process. No alterations are made it the file itself. _filepath_ parameter specifies path to .jsonc file. | ||
|
||
from jsonc_parser.parser import JsoncParser | ||
|
||
file_path = "./data.jsonc" | ||
# Content from 'data.jsonc' -> {"version": "1.0.0" /*This is my project's version*/} | ||
|
||
data = JsoncParser.parse_file(file_path) | ||
|
||
print(data) | ||
# Output: {'version': '1.0.0'} | ||
|
||
This function can raise _[FunctionParameterError](#exc-function-parameter-error)_ if filepath parameter is not a path-like object (str, bytes object representing a path, or os.PathLike compliant) or is empty. Also this function will raise _[FileError](#exc-file-error)_ exception if file's format is unsupported and a _[ParserError](#exc-parser-error)_ exception if file cannot be parsed/contains invalid JSON data. | ||
|
||
- ##### JsoncParser.parse_str(_string: str) -> dict | ||
|
||
This function parses string, specified in __string_ parameter, and deserializes it into a valid Python object (dictionary), removing any comment in the process. | ||
|
||
from jsonc_parser.parser import JsoncParser | ||
|
||
json_string = """{"version": "1.0.0" /*This is my project's version*/}""" | ||
|
||
data = JsoncParser.parse_str(json_string) | ||
|
||
print(data) | ||
# Output: {'version': '1.0.0'} | ||
|
||
This function can raise _[FunctionParameterError](#exc-function-parameter-error)_ if __string_ parameter is not a string or is empty. Also this function will raise a _[ParserError](#exc-parser-error)_ exception if file cannot be parsed/contains invalid JSON data. | ||
|
||
##### JsoncParser.convert_to_json(filepath: PathLike, remove_file: bool = False) -> None | ||
This function converts file from .jsonc to .json format, removing any comments in the process. filepath parameter specifies path to file and remove_file parameter specifies if .jsonc file will be removed (deleted from hard drive) after conversion. If set to True, this function will delete .jsonc file leaving only .json file. Otherwise, both files are not deleted. This function can raise _[FunctionParameterError](#exc-function-parameter-error)_ if _filepath_ parameter is not a path-like object or is empty or if _remove_file_ parameter is not a boolean. | ||
|
||
- ##### JsoncParser.convert_to_jsonc(filepath: PathLike, remove_file: bool = False) -> None | ||
This function converts file from .json to .jsonc format, enabling comment support. filepath parameter specifies path to file and _remove_file_ parameter specifies if .jsonc file will be removed (deleted from hard drive) after conversion. If set to True, this function will delete .jsonc file leaving only .json file. Otherwise, both files are not deleted. | ||
This function can raise _[FunctionParameterError](#exc-function-parameter-error)_ if _filepath_ parameter is not a path-like object or is empty or if _remove_file_ parameter is not a boolean. | ||
|
||
## Exceptions | ||
|
||
There are a total of 3 custom exceptions that jsonc-parser can raise during its runtime. To access the in your script, simply import them from jsonc_parser.errors module: | ||
|
||
from jsonc_parser.errors import FileError, IncorrectParameterError, ParserError | ||
|
||
#### Exceptions: | ||
|
||
- **FileError** | ||
<div id='exc-file-error'></div> | ||
This exception indicates that there is a problem with selected file. | ||
|
||
- **FunctionParameterError** | ||
<div id='exc-function-parameter-error'></div> | ||
This exception indicates that some of function's parameters are invalid. They may have wrong type, have invalid values or be erroneous in some other way. | ||
|
||
- **ParserError** | ||
<div id='exc-parser-error'></div> | ||
This exception indicates that file cannot be parsed. It can have wrong extension, invalid data, etc. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
class FunctionParameterError(Exception): | ||
""" | ||
This excption indicates that one or more of function's parameters are incorrect | ||
""" | ||
|
||
def __init__(self, *args): | ||
self.__msg = args[0] | ||
super().__init__(self.__msg) | ||
|
||
def __str__(self): | ||
return self.__msg | ||
|
||
|
||
class FileError(Exception): | ||
""" | ||
This exception indicates that file format cannot be parsed | ||
""" | ||
|
||
def __init__(self, *args: object) -> None: | ||
super().__init__(*args) | ||
|
||
def __str__(self) -> str: | ||
return super().__str__() | ||
|
||
|
||
class ParserError(Exception): | ||
""" | ||
This exception indicates that file cannot be parsed | ||
""" | ||
|
||
def __init__(self, *args: object) -> None: | ||
super().__init__(*args) | ||
|
||
def __str__(self) -> str: | ||
return super().__str__() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
本文件夹中以下内容已移至上级目录: | ||
|
||
- `__init__.py` | ||
- `parser.py` | ||
- `errors.py` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
import json | ||
import re | ||
from jsonc_parser.errors import FileError, FunctionParameterError, ParserError | ||
import os | ||
from typing import Union | ||
|
||
|
||
class JsoncParser: | ||
|
||
# regex = re.compile(r"//.*?\n|/\*.*?\*/", re.MULTILINE | re.DOTALL) | ||
regex = re.compile(r"(\".*?\"|\'.*?\')|(/\*.*?\*/|//[^\r\n]*$)", re.MULTILINE | re.DOTALL) | ||
newline_replace_regex = re.compile("\n{2,}", re.MULTILINE) | ||
|
||
def parse_str(_string: str) -> dict: | ||
""" | ||
Parse JSON-as-string and deserialize its content into Python dictionary, | ||
ignoring any comments. | ||
Parameters: `_string:str` - path to file | ||
This function will raise a `FunctionParameterError` exception if `_string` parameter | ||
has an incorrect type or is empty. | ||
This function will raise a `ParserError` exception if the string cannot be parsed. | ||
This function will raise any additional exceptions if occurred. | ||
""" | ||
|
||
def __re_sub(match): | ||
if match.group(2) is not None: | ||
return "" | ||
else: | ||
return match.group(1) | ||
|
||
if type(_string) != str: | ||
raise FunctionParameterError( | ||
"_string parameter must be str; got {} instead".format(type(_string).__name__) | ||
) | ||
|
||
try: | ||
data = JsoncParser.regex.sub(__re_sub, _string) | ||
return json.loads(JsoncParser.regex.sub(__re_sub, data)) | ||
except Exception as e: | ||
raise ParserError("{} file cannot be parsed (message: {})".format(_string, str(e))) | ||
|
||
@staticmethod | ||
def parse_file(filepath: Union[str, os.PathLike], encoding: str = None) -> dict: | ||
""" | ||
Parse .jsonc file and deserialize its content into Python dictionary, | ||
ignoring any comments. | ||
Parameters: | ||
`filepath: str | os.PathLike` - path to file | ||
`encoding: str = None` - option of open() | ||
This function will raise a `FunctionParameterError` exception if `filepath` parameter | ||
has an incorrect type or is empty. | ||
This function will raise a `FileError` exception if file format is unsupported. | ||
This function will raise a `ParserError` exception if file cannot be parsed. | ||
This function will raise any additional exceptions if occurred. | ||
""" | ||
|
||
def __re_sub(match): | ||
if match.group(2) is not None: | ||
return "" | ||
else: | ||
return match.group(1) | ||
|
||
# verify that provided path is a valid path-like object | ||
try: | ||
filepath = os.fspath(filepath) | ||
except TypeError: | ||
raise FunctionParameterError( | ||
"filepath parameter must be path-like; got {} instead".format(type(filepath).__name__) | ||
) | ||
|
||
if not filepath: | ||
raise FunctionParameterError("path is empty.") | ||
|
||
if not os.path.exists(filepath) or not os.path.isfile(filepath): | ||
raise FileError("{} does not exist or is not a file".format(filepath)) | ||
|
||
if filepath.split(".")[-1] not in ["json", "jsonc"]: | ||
raise FileError("file {} has an unsupported extension.".format(filepath)) | ||
|
||
json_file = open(filepath, "r", encoding=encoding) | ||
data_raw = json_file.read() | ||
json_file.close() | ||
|
||
try: | ||
data = JsoncParser.regex.sub(__re_sub, data_raw) | ||
return json.loads(JsoncParser.regex.sub(__re_sub, data)) | ||
except Exception as e: | ||
raise ParserError("{} file cannot be parsed (message: {})".format(filepath, str(e))) | ||
|
||
@staticmethod | ||
def convert_to_json( | ||
filepath: Union[str, os.PathLike], | ||
remove_file: bool = False, | ||
encoding: str = None, | ||
ensure_ascii: bool = True, | ||
) -> None: | ||
""" | ||
Convert file from .jsonc to .json format, removing any comments from it | ||
Parameters: `path: str | os.PathLike` is a path to file, `remove_file:bool` indicates if | ||
source file will be deleted or not. If set to True, .jsonc file will be deleted from the | ||
hard drive, otherwise file remains alongside with its .json output. | ||
`encoding: str = None` - option of open() | ||
`ensure_ascii: bool = True` - option of json.dump() | ||
This function will raise a `FunctionParameterError` if one or more of function's parameters | ||
has an incorrect type/invalid value. | ||
This function will raise any additional exceptions if occurred. | ||
""" | ||
|
||
# verify that provided path is a valid path-like object | ||
try: | ||
filepath = os.fspath(filepath) | ||
except TypeError: | ||
raise FunctionParameterError( | ||
"filepath parameter must be path-like; got {} instead".format(type(filepath).__name__) | ||
) | ||
|
||
if not filepath: | ||
raise FunctionParameterError("path is empty.") | ||
|
||
if type(remove_file) != bool: | ||
raise FunctionParameterError( | ||
"remove_file parameter must be bool; got {} instead.".format( | ||
type(remove_file).__name__ | ||
) | ||
) | ||
|
||
data = JsoncParser.parse_file(filepath, encoding=encoding) | ||
|
||
if remove_file: | ||
os.remove(filepath) | ||
|
||
new_filename = os.path.splitext(filepath)[0] + ".json" | ||
if os.path.exists(new_filename) and os.path.isfile(new_filename): | ||
raise FileError("{} file already exists".format(new_filename)) | ||
|
||
json_file = open(new_filename, "x", encoding=encoding) | ||
json_file.write(json.dumps(data, indent=2, ensure_ascii=ensure_ascii)) | ||
json_file.close() | ||
|
||
@staticmethod | ||
def convert_to_jsonc( | ||
filepath: Union[str, os.PathLike], | ||
remove_file: bool = False, | ||
encoding: str = None, | ||
ensure_ascii: bool = True | ||
): | ||
""" | ||
Convert file .jsonc format, enabling comments. | ||
Parameters: `filepath: str | os.PathLike` is a path to file, `remove_file:bool` indicates | ||
if source file will be deleted or not. If set to True, .json file will be deleted from the | ||
hard drive, otherwise file remains alongside with its .jsonc output. | ||
`encoding: str = None` - option of open() | ||
`ensure_ascii: bool = True` - option of json.dump() | ||
This function will raise a `FunctionParameterError` if one or more of function's parameters | ||
has an incorrect type/invalid value. | ||
This function will raise any additional exceptions if occurred. | ||
""" | ||
# verify that provided path is a valid path-like object | ||
try: | ||
filepath = os.fspath(filepath) | ||
except TypeError: | ||
raise FunctionParameterError( | ||
"filepath parameter must be path-like; got {} instead".format(type(filepath).__name__) | ||
) | ||
|
||
if not filepath: | ||
raise FunctionParameterError("path is empty.") | ||
|
||
if type(remove_file) != bool: | ||
raise FunctionParameterError( | ||
"remove_file parameter must be bool; got {} instead.".format( | ||
type(remove_file).__name__ | ||
) | ||
) | ||
|
||
data = JsoncParser.parse_file(filepath, encoding=encoding) | ||
|
||
if remove_file: | ||
os.remove(filepath) | ||
|
||
new_filename = os.path.splitext(filepath)[0] + ".jsonc" | ||
if os.path.exists(new_filename) and os.path.isfile(new_filename): | ||
raise FileError("{} file already exists".format(new_filename)) | ||
|
||
json_file = open(new_filename, "x", encoding=encoding) | ||
json_file.write(json.dumps(data, indent=2, ensure_ascii=ensure_ascii)) | ||
json_file.close() |
Oops, something went wrong.