pyeasyphd 0.0.9__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyeasyphd might be problematic. Click here for more details.
- pyeasyphd/.python-version +1 -1
- pyeasyphd/main/__init__.py +0 -4
- pyeasyphd/main/basic_input.py +7 -63
- pyeasyphd/main/python_run_md.py +3 -3
- pyeasyphd/pyeasyphd.sublime-settings +1 -159
- pyeasyphd/tools/__init__.py +1 -16
- pyeasyphd/tools/generate/generate_from_bibs.py +54 -330
- pyeasyphd/tools/generate/generate_html.py +122 -0
- pyeasyphd/tools/generate/generate_library.py +188 -0
- pyeasyphd/tools/generate/generate_links.py +13 -6
- pyeasyphd/tools/py_run_bib_md_tex.py +11 -12
- pyeasyphd/tools/search/search_base.py +8 -5
- pyeasyphd/tools/search/search_core.py +4 -3
- pyeasyphd/tools/search/search_keywords.py +1 -1
- pyeasyphd/tools/search/search_writers.py +8 -5
- {pyeasyphd-0.0.9.dist-info → pyeasyphd-0.1.1.dist-info}/METADATA +3 -6
- pyeasyphd-0.1.1.dist-info/RECORD +27 -0
- pyeasyphd/bib/__init__.py +0 -1
- pyeasyphd/bib/bibtexbase/__init__.py +0 -7
- pyeasyphd/bib/bibtexbase/standardize/_base.py +0 -36
- pyeasyphd/bib/bibtexbase/standardize/default_data.py +0 -97
- pyeasyphd/bib/bibtexbase/standardize/do_on_bib.py +0 -54
- pyeasyphd/bib/bibtexbase/standardize/do_on_comment_block.py +0 -38
- pyeasyphd/bib/bibtexbase/standardize/do_on_entry_block.py +0 -310
- pyeasyphd/bib/bibtexbase/standardize/do_on_preamble_block.py +0 -35
- pyeasyphd/bib/bibtexbase/standardize/do_on_string_block.py +0 -34
- pyeasyphd/bib/bibtexbase/standardize_bib.py +0 -75
- pyeasyphd/bib/bibtexparser/__init__.py +0 -47
- pyeasyphd/bib/bibtexparser/bibtex_format.py +0 -87
- pyeasyphd/bib/bibtexparser/exceptions.py +0 -64
- pyeasyphd/bib/bibtexparser/library.py +0 -207
- pyeasyphd/bib/bibtexparser/middlewares/block/add.py +0 -94
- pyeasyphd/bib/bibtexparser/middlewares/block/authors.py +0 -22
- pyeasyphd/bib/bibtexparser/middlewares/block/doi_url.py +0 -62
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_normalize.py +0 -47
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_replace.py +0 -31
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_values_normalize.py +0 -222
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_delete.py +0 -34
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_keep.py +0 -33
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_sort.py +0 -70
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_types.py +0 -15
- pyeasyphd/bib/bibtexparser/middlewares/block/journal_booktitle.py +0 -113
- pyeasyphd/bib/bibtexparser/middlewares/block/month_year.py +0 -34
- pyeasyphd/bib/bibtexparser/middlewares/block/number_volume.py +0 -21
- pyeasyphd/bib/bibtexparser/middlewares/block/pages.py +0 -28
- pyeasyphd/bib/bibtexparser/middlewares/block/title.py +0 -20
- pyeasyphd/bib/bibtexparser/middlewares/library/generating_entrykeys.py +0 -98
- pyeasyphd/bib/bibtexparser/middlewares/library/keeping_blocks.py +0 -29
- pyeasyphd/bib/bibtexparser/middlewares/library/sorting_blocks.py +0 -124
- pyeasyphd/bib/bibtexparser/middlewares/middleware.py +0 -222
- pyeasyphd/bib/bibtexparser/middlewares/parsestack.py +0 -13
- pyeasyphd/bib/bibtexparser/middlewares/utils.py +0 -226
- pyeasyphd/bib/bibtexparser/middlewares_library_to_library.py +0 -414
- pyeasyphd/bib/bibtexparser/middlewares_library_to_str.py +0 -42
- pyeasyphd/bib/bibtexparser/middlewares_str_to_library.py +0 -35
- pyeasyphd/bib/bibtexparser/middlewares_str_to_str.py +0 -29
- pyeasyphd/bib/bibtexparser/model.py +0 -481
- pyeasyphd/bib/bibtexparser/splitter.py +0 -151
- pyeasyphd/bib/core/__init__.py +0 -18
- pyeasyphd/bib/core/convert_library_to_library.py +0 -31
- pyeasyphd/bib/core/convert_library_to_str.py +0 -199
- pyeasyphd/bib/core/convert_str_to_library.py +0 -34
- pyeasyphd/bib/core/convert_str_to_str.py +0 -27
- pyeasyphd/main/python_run_bib.py +0 -73
- pyeasyphd/main/python_writers.py +0 -212
- pyeasyphd/tools/compare/compare_bibs.py +0 -234
- pyeasyphd/tools/experiments_base.py +0 -203
- pyeasyphd/tools/format_save_bibs.py +0 -178
- pyeasyphd/tools/replace/replace.py +0 -81
- pyeasyphd/tools/spider/process_spider_bib.py +0 -247
- pyeasyphd/tools/spider/process_spider_url.py +0 -75
- pyeasyphd/tools/spider/process_spider_url_bib.py +0 -62
- pyeasyphd-0.0.9.dist-info/RECORD +0 -80
- {pyeasyphd-0.0.9.dist-info → pyeasyphd-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
|
|
3
|
-
from ...library import Library
|
|
4
|
-
from ...model import Entry
|
|
5
|
-
from ..middleware import LibraryMiddleware
|
|
6
|
-
from ..utils import SKIP_WORD_IN_CITATION_KEY, generate_cite_key_prefix
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class GenerateEntriesCiteKey(LibraryMiddleware):
|
|
10
|
-
"""Generate entries key of a library.
|
|
11
|
-
|
|
12
|
-
The entry.key is also `Cite Key`.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
# docstr-coverage: inherited
|
|
16
|
-
def __init__(
|
|
17
|
-
self,
|
|
18
|
-
full_abbr_article_dict: dict,
|
|
19
|
-
full_abbr_inproceedings_dict: dict,
|
|
20
|
-
full_names_in_json: str,
|
|
21
|
-
abbr_names_in_json: str,
|
|
22
|
-
allow_inplace_modification: bool = True
|
|
23
|
-
):
|
|
24
|
-
super().__init__(allow_inplace_modification=allow_inplace_modification)
|
|
25
|
-
|
|
26
|
-
self.full_abbr_article_dict = full_abbr_article_dict
|
|
27
|
-
self.full_abbr_inproceedings_dict = full_abbr_inproceedings_dict
|
|
28
|
-
self.full_names_in_json = full_names_in_json
|
|
29
|
-
self.abbr_names_in_json = abbr_names_in_json
|
|
30
|
-
|
|
31
|
-
# docstr-coverage: inherited
|
|
32
|
-
def transform(self, library: Library) -> Library:
|
|
33
|
-
library = super().transform(library)
|
|
34
|
-
for entry in library.entries:
|
|
35
|
-
generate_key = self.generate_cite_key(entry)
|
|
36
|
-
while generate_key in [e.key for e in library.entries if e != entry]:
|
|
37
|
-
generate_key = generate_key + "-a"
|
|
38
|
-
entry.key = generate_key
|
|
39
|
-
return library
|
|
40
|
-
|
|
41
|
-
def generate_cite_key(self, entry: Entry) -> str:
|
|
42
|
-
"""Generate user citation key."""
|
|
43
|
-
prefix = generate_cite_key_prefix(
|
|
44
|
-
entry,
|
|
45
|
-
self.full_abbr_article_dict,
|
|
46
|
-
self.full_abbr_inproceedings_dict,
|
|
47
|
-
self.full_names_in_json,
|
|
48
|
-
self.abbr_names_in_json
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
cite_key = self.generate_google_cite_key(entry)
|
|
52
|
-
if prefix != "":
|
|
53
|
-
cite_key = prefix + "_" + cite_key
|
|
54
|
-
return cite_key
|
|
55
|
-
|
|
56
|
-
@staticmethod
|
|
57
|
-
def _obtain_family_name(author: str) -> str:
|
|
58
|
-
"""Obtain the family name of first author."""
|
|
59
|
-
author = re.sub(r"\noopsort", "", author)
|
|
60
|
-
author = re.sub("}{", " ", author)
|
|
61
|
-
if re.search(r"\s+and\s+", author): # Zhe Feng, Tianxi Li, Haifeng Xu and Fei Zhang
|
|
62
|
-
author = re.split(r"\s+and\s+", author)[0]
|
|
63
|
-
|
|
64
|
-
if re.search(r",", author): # Zhe Feng, Tianxi Li, Haifeng Xu
|
|
65
|
-
author = re.split(r",", author)[0]
|
|
66
|
-
|
|
67
|
-
author = author.strip()
|
|
68
|
-
|
|
69
|
-
if re.search(r"\s+", author): # M. Li or Ming Li (given name family name)
|
|
70
|
-
f_list = re.split(r"\s+", author)
|
|
71
|
-
f_list = [f.strip() for f in f_list if len(f.strip()) != 0]
|
|
72
|
-
family_name = f_list[-1]
|
|
73
|
-
else:
|
|
74
|
-
family_name = author
|
|
75
|
-
return family_name
|
|
76
|
-
|
|
77
|
-
def generate_google_cite_key(self, entry: Entry) -> str:
|
|
78
|
-
"""Generate google citation key."""
|
|
79
|
-
author = entry["author"] if "author" in entry else ""
|
|
80
|
-
family_name = self._obtain_family_name(author).lower()
|
|
81
|
-
|
|
82
|
-
year = entry["year"] if "year" in entry else ""
|
|
83
|
-
|
|
84
|
-
first_word_of_title = ""
|
|
85
|
-
title = entry["title"] if "title" in entry else ""
|
|
86
|
-
regex = re.compile(r"\\href{(.*)}{(.*)}")
|
|
87
|
-
if mch := regex.search(title):
|
|
88
|
-
title = mch.group(2)
|
|
89
|
-
|
|
90
|
-
word_list = [w.lower() for w in re.split(r"\s+", title) if w.strip()]
|
|
91
|
-
word_list = [re.sub(r"[^a-zA-Z0-9]", "", w) for w in word_list]
|
|
92
|
-
for w in word_list:
|
|
93
|
-
if w not in SKIP_WORD_IN_CITATION_KEY:
|
|
94
|
-
first_word_of_title = w
|
|
95
|
-
break
|
|
96
|
-
|
|
97
|
-
citation_key = family_name + year + first_word_of_title
|
|
98
|
-
return re.sub(r"[^a-zA-Z0-9]", "", citation_key)
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
from ...library import Library
|
|
4
|
-
from ..middleware import LibraryMiddleware
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class KeepEntriesByCiteKey(LibraryMiddleware):
|
|
8
|
-
"""Keep the entries of a library by `Cite Key`.
|
|
9
|
-
|
|
10
|
-
The entry.key is also `Cite Key`.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
def __init__(self, entry_keys: List[str], allow_inplace_modification: bool = True):
|
|
14
|
-
super().__init__(allow_inplace_modification=allow_inplace_modification)
|
|
15
|
-
|
|
16
|
-
self.entry_keys = [e.lower() for e in entry_keys]
|
|
17
|
-
|
|
18
|
-
# docstr-coverage: inherited
|
|
19
|
-
def transform(self, library: Library) -> Library:
|
|
20
|
-
library = super().transform(library)
|
|
21
|
-
for entry in library.entries:
|
|
22
|
-
if entry.key.lower() not in self.entry_keys:
|
|
23
|
-
library.remove(entry)
|
|
24
|
-
return library
|
|
25
|
-
|
|
26
|
-
# docstr-coverage: inherited
|
|
27
|
-
@classmethod
|
|
28
|
-
def metadata_key(cls) -> str:
|
|
29
|
-
return "keep_entry_according_cite_keys"
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from copy import deepcopy
|
|
3
|
-
from typing import List
|
|
4
|
-
|
|
5
|
-
from ...library import Library
|
|
6
|
-
from ...model import (
|
|
7
|
-
Block,
|
|
8
|
-
Entry,
|
|
9
|
-
ExplicitComment,
|
|
10
|
-
ImplicitComment,
|
|
11
|
-
ParsingFailedBlock,
|
|
12
|
-
Preamble,
|
|
13
|
-
String,
|
|
14
|
-
)
|
|
15
|
-
from ..middleware import LibraryMiddleware
|
|
16
|
-
|
|
17
|
-
DEFAULT_BLOCK_TYPE_ORDER = (ImplicitComment, ExplicitComment, String, Preamble, Entry, ParsingFailedBlock, Block)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class SortBlocksByTypeAndUserSortKeyMiddleware(LibraryMiddleware):
|
|
21
|
-
"""Sorts the blocks of a library by type and `User Sort Key`."""
|
|
22
|
-
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
keep_entry_according_cite_keys: List[str] = [],
|
|
26
|
-
sort_entry_according_field_keys: List[str] = ["year", "volume", "number", "month", "pages"],
|
|
27
|
-
sort_entry_according_field_keys_reverse: bool = True,
|
|
28
|
-
):
|
|
29
|
-
self._verify_all_types_are_block_types(DEFAULT_BLOCK_TYPE_ORDER)
|
|
30
|
-
self.keep_entry_according_cite_keys = keep_entry_according_cite_keys
|
|
31
|
-
self.sort_entry_according_field_keys = sort_entry_according_field_keys
|
|
32
|
-
self.sort_entry_according_field_keys_reverse = sort_entry_according_field_keys_reverse
|
|
33
|
-
|
|
34
|
-
# In-place modification is not yet supported, we make this explicit here,
|
|
35
|
-
super().__init__(allow_inplace_modification=False)
|
|
36
|
-
|
|
37
|
-
@staticmethod
|
|
38
|
-
def _verify_all_types_are_block_types(sort_order):
|
|
39
|
-
for t in sort_order:
|
|
40
|
-
if not issubclass(t, Block):
|
|
41
|
-
raise ValueError(
|
|
42
|
-
"Sort order must only contain Block subclasses, " f"but got {str(t)}"
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
# docstr-coverage: inherited
|
|
46
|
-
def transform(self, library: Library) -> Library:
|
|
47
|
-
library = super().transform(library)
|
|
48
|
-
blocks = library.blocks
|
|
49
|
-
|
|
50
|
-
_blocks = []
|
|
51
|
-
|
|
52
|
-
_implicit_comments = [b for b in blocks if isinstance(b, ImplicitComment)]
|
|
53
|
-
_implicit_comments = sorted(_implicit_comments, key=lambda x: len(x.comment), reverse=False)
|
|
54
|
-
|
|
55
|
-
_explicit_comments = [b for b in blocks if isinstance(b, ExplicitComment)]
|
|
56
|
-
_explicit_comments = sorted(_explicit_comments, key=lambda x: len(x.comment), reverse=False)
|
|
57
|
-
|
|
58
|
-
_strings = sorted(library.strings, key=lambda x: x.key, reverse=False)
|
|
59
|
-
|
|
60
|
-
_preambles = sorted(library.preambles, key=lambda x: len(x.value), reverse=False)
|
|
61
|
-
|
|
62
|
-
_entries = library.entries
|
|
63
|
-
if self.keep_entry_according_cite_keys:
|
|
64
|
-
_entries = sorted(_entries, key=self._sort_entry_one, reverse=False)
|
|
65
|
-
else:
|
|
66
|
-
_entries = sorted(_entries, key=self._sort_entry_two, reverse=self.sort_entry_according_field_keys_reverse)
|
|
67
|
-
|
|
68
|
-
_failed_blocks = deepcopy(library.failed_blocks)
|
|
69
|
-
_failed_blocks = sorted(_failed_blocks, key=lambda x: len(x.__class__.__name__), reverse=False)
|
|
70
|
-
|
|
71
|
-
_others = [b for b in blocks if not (
|
|
72
|
-
isinstance(b, ImplicitComment) or
|
|
73
|
-
isinstance(b, ExplicitComment) or
|
|
74
|
-
isinstance(b, String) or
|
|
75
|
-
isinstance(b, Preamble) or
|
|
76
|
-
isinstance(b, Entry) or
|
|
77
|
-
isinstance(b, ParsingFailedBlock)
|
|
78
|
-
)
|
|
79
|
-
]
|
|
80
|
-
_others = sorted(_others, key=lambda x: len(x.__class__.__name__), reverse=False)
|
|
81
|
-
|
|
82
|
-
# order of blocks
|
|
83
|
-
_blocks.extend(_strings)
|
|
84
|
-
_blocks.extend(_entries)
|
|
85
|
-
_blocks.extend(_preambles)
|
|
86
|
-
_blocks.extend(_explicit_comments)
|
|
87
|
-
_blocks.extend(_implicit_comments)
|
|
88
|
-
_blocks.extend(_failed_blocks)
|
|
89
|
-
_blocks.extend(_others)
|
|
90
|
-
return Library(blocks=_blocks)
|
|
91
|
-
|
|
92
|
-
# docstr-coverage: inherited
|
|
93
|
-
@classmethod
|
|
94
|
-
def metadata_key(cls) -> str:
|
|
95
|
-
return "sort_blocks_by_type_and_user_sort_key"
|
|
96
|
-
|
|
97
|
-
def _sort_entry_one(self, entry):
|
|
98
|
-
if entry.key in self.keep_entry_according_cite_keys:
|
|
99
|
-
return self.keep_entry_according_cite_keys.index(entry.key)
|
|
100
|
-
else:
|
|
101
|
-
return -1
|
|
102
|
-
|
|
103
|
-
def _sort_entry_two(self, entry):
|
|
104
|
-
_sorting_index = []
|
|
105
|
-
_sorting_index.append(entry.entry_type)
|
|
106
|
-
for k in self.sort_entry_according_field_keys:
|
|
107
|
-
if k in entry.fields_dict:
|
|
108
|
-
v = entry.fields_dict[k].value
|
|
109
|
-
# for sorting
|
|
110
|
-
if k == "pages":
|
|
111
|
-
v = v.split("——")[0].split("--")[0].split("–")[0].split("-")[0]
|
|
112
|
-
if k == "month":
|
|
113
|
-
v = v.split("–")[0].split("-")[0].split("/")[0]
|
|
114
|
-
_sorting_index.append(v)
|
|
115
|
-
else:
|
|
116
|
-
_sorting_index.append("0")
|
|
117
|
-
return self.sort_strings_with_embedded_numbers("_".join(_sorting_index))
|
|
118
|
-
|
|
119
|
-
@staticmethod
|
|
120
|
-
def sort_strings_with_embedded_numbers(s: str) -> List[str]:
|
|
121
|
-
re_digits = re.compile(r"(\d+)")
|
|
122
|
-
pieces = re_digits.split(s)
|
|
123
|
-
pieces[1::2] = map(int, pieces[1::2])
|
|
124
|
-
return pieces
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import logging
|
|
3
|
-
from copy import deepcopy
|
|
4
|
-
from typing import Collection, Union
|
|
5
|
-
|
|
6
|
-
from ..library import Library
|
|
7
|
-
from ..model import Block, Entry, ExplicitComment, ImplicitComment, Preamble, String
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Middleware(abc.ABC):
|
|
13
|
-
"""Implements a function to transform a block or library.
|
|
14
|
-
|
|
15
|
-
Abstract Class. You should extend either BlockMiddleware
|
|
16
|
-
or LibraryMiddleware
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
def __init__(
|
|
20
|
-
self,
|
|
21
|
-
allow_parallel_execution: bool = True,
|
|
22
|
-
allow_inplace_modification: bool = True,
|
|
23
|
-
):
|
|
24
|
-
"""Create a new Middleware.
|
|
25
|
-
|
|
26
|
-
:param allow_inplace_modification: See corresponding property.
|
|
27
|
-
:param allow_parallel_execution: See corresponding property.
|
|
28
|
-
"""
|
|
29
|
-
self._allow_inplace_modification = allow_inplace_modification
|
|
30
|
-
self._allow_parallel_execution = allow_parallel_execution
|
|
31
|
-
|
|
32
|
-
@property
|
|
33
|
-
def allow_inplace_modification(self) -> bool:
|
|
34
|
-
"""If true, the middleware **may** modify the block in-place.
|
|
35
|
-
|
|
36
|
-
I.e., if true, the output of `transform` may be the same instance
|
|
37
|
-
as the input. If false, new instances must be returned.
|
|
38
|
-
"""
|
|
39
|
-
return self._allow_inplace_modification
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def allow_parallel_execution(self) -> bool:
|
|
43
|
-
"""True indicates that the middleware is threadsafe."""
|
|
44
|
-
return self._allow_parallel_execution
|
|
45
|
-
|
|
46
|
-
@abc.abstractmethod
|
|
47
|
-
def transform(self, library: Library) -> Library:
|
|
48
|
-
"""Apply transformation to a library. Main entrypoint of the middleware."""
|
|
49
|
-
raise NotImplementedError("called abstract method")
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class BlockMiddleware(Middleware, abc.ABC):
|
|
53
|
-
"""Transform a library on a per-block basis.
|
|
54
|
-
|
|
55
|
-
The `BlockMiddleware` replaces a block with zero, one or more
|
|
56
|
-
new (transformed) blocks.
|
|
57
|
-
|
|
58
|
-
Changes may rely on the state of the overall library,
|
|
59
|
-
but must not change the state of the library directly,
|
|
60
|
-
except if `allow_inplace_modification` is true.
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
@classmethod
|
|
64
|
-
def metadata_key(cls) -> str:
|
|
65
|
-
"""Tt is the identifier of the middleware.
|
|
66
|
-
|
|
67
|
-
This key is used to identify the middleware in a blocks metadata.
|
|
68
|
-
"""
|
|
69
|
-
return cls.__name__
|
|
70
|
-
|
|
71
|
-
# docstr-coverage: inherited
|
|
72
|
-
def transform(self, library: Library) -> Library:
|
|
73
|
-
# TODO Multiprocessing (only for large library and if allow_multi..)
|
|
74
|
-
blocks = []
|
|
75
|
-
for b in library.blocks:
|
|
76
|
-
transformed = self.transform_block(b, library)
|
|
77
|
-
# Case 1: None. Skip it.
|
|
78
|
-
if transformed is None:
|
|
79
|
-
pass
|
|
80
|
-
|
|
81
|
-
# Case 2: A single block. Add it to the list.
|
|
82
|
-
elif isinstance(transformed, Block):
|
|
83
|
-
blocks.append(transformed)
|
|
84
|
-
|
|
85
|
-
# Case 3: A collection. Append all the elements.
|
|
86
|
-
elif isinstance(transformed, Collection):
|
|
87
|
-
# check that all the items are indeed blocks
|
|
88
|
-
for item in transformed:
|
|
89
|
-
if not isinstance(item, Block):
|
|
90
|
-
raise TypeError(
|
|
91
|
-
f"Non-Block type found in transformed collection: {type(item)}"
|
|
92
|
-
)
|
|
93
|
-
blocks.extend(transformed)
|
|
94
|
-
|
|
95
|
-
# Case 4: Something else. Error.
|
|
96
|
-
else:
|
|
97
|
-
raise TypeError(f"Illegal output type from transform_block: {type(transformed)}")
|
|
98
|
-
return Library(blocks=blocks)
|
|
99
|
-
|
|
100
|
-
def transform_block(
|
|
101
|
-
self, block: Block, library: Library
|
|
102
|
-
) -> Union[Block, Collection[Block], None]:
|
|
103
|
-
"""Transform a block.
|
|
104
|
-
|
|
105
|
-
:param block: Block to transform.
|
|
106
|
-
:param library: Library containing the block.
|
|
107
|
-
Should typically not be modified during
|
|
108
|
-
the transformation, but be considered as read-only.
|
|
109
|
-
If the library is modified, make sure to set the `allow_multithreading`
|
|
110
|
-
constructor argument to false
|
|
111
|
-
:return: Transformed block. If the block should be removed, return None.
|
|
112
|
-
If the block should be replaced by multiple blocks, return a collection
|
|
113
|
-
of blocks. If the block should be replaced by a single block, return
|
|
114
|
-
the single block. If the block should not be modified, return a copy of
|
|
115
|
-
the original block.
|
|
116
|
-
The returned block has to be a new instance, except if
|
|
117
|
-
`self.allow_inplace_modification` is True (in which case the block
|
|
118
|
-
may also return the original block).
|
|
119
|
-
"""
|
|
120
|
-
block = block if self.allow_inplace_modification else deepcopy(block)
|
|
121
|
-
if isinstance(block, Entry):
|
|
122
|
-
return self.transform_entry(block, library)
|
|
123
|
-
elif isinstance(block, String):
|
|
124
|
-
return self.transform_string(block, library)
|
|
125
|
-
elif isinstance(block, Preamble):
|
|
126
|
-
return self.transform_preamble(block, library)
|
|
127
|
-
elif isinstance(block, ExplicitComment):
|
|
128
|
-
return self.transform_explicit_comment(block, library)
|
|
129
|
-
elif isinstance(block, ImplicitComment):
|
|
130
|
-
return self.transform_implicit_comment(block, library)
|
|
131
|
-
|
|
132
|
-
# logger.warning(f"Unknown block type {type(block)}")
|
|
133
|
-
return block
|
|
134
|
-
|
|
135
|
-
def transform_entry(
|
|
136
|
-
self, entry: Entry, library: Library
|
|
137
|
-
) -> Union[Block, Collection[Block], None]:
|
|
138
|
-
"""Transform an entry. Called by `transform_block` if the block is an entry.
|
|
139
|
-
|
|
140
|
-
Note: This method modifies the passed entry. For a method
|
|
141
|
-
respecting the `allow_inplace_modification` property,
|
|
142
|
-
you should use `transform` or `transform_block` instead.
|
|
143
|
-
"""
|
|
144
|
-
return entry
|
|
145
|
-
|
|
146
|
-
def transform_string(
|
|
147
|
-
self, string: String, library: Library
|
|
148
|
-
) -> Union[Block, Collection[Block], None]:
|
|
149
|
-
"""Transform a string. Called by `transform_block` if the block is a string.
|
|
150
|
-
|
|
151
|
-
Note: This method modifies the passed string. For a method
|
|
152
|
-
respecting the `allow_inplace_modification` property,
|
|
153
|
-
you should use `transform` or `transform_block` instead.
|
|
154
|
-
"""
|
|
155
|
-
return string
|
|
156
|
-
|
|
157
|
-
def transform_preamble(
|
|
158
|
-
self, preamble: Preamble, library: Library
|
|
159
|
-
) -> Union[Block, Collection[Block], None]:
|
|
160
|
-
"""Transform a preamble. Called by `transform_block` if the block is a preamble.
|
|
161
|
-
|
|
162
|
-
Note: This method modifies the passed preamble. For a method
|
|
163
|
-
respecting the `allow_inplace_modification` property,
|
|
164
|
-
you should use `transform` or `transform_block` instead.
|
|
165
|
-
"""
|
|
166
|
-
return preamble
|
|
167
|
-
|
|
168
|
-
def transform_explicit_comment(
|
|
169
|
-
self, explicit_comment: ExplicitComment, library: Library
|
|
170
|
-
) -> Union[Block, Collection[Block], None]:
|
|
171
|
-
"""Transform an explicit comment. Called by `transform_block` if the block is an explicit comment.
|
|
172
|
-
|
|
173
|
-
Note: This method modifies the passed explicit comment. For a method
|
|
174
|
-
respecting the `allow_inplace_modification` property,
|
|
175
|
-
you should use `transform` or `transform_block` instead.
|
|
176
|
-
"""
|
|
177
|
-
return explicit_comment
|
|
178
|
-
|
|
179
|
-
def transform_implicit_comment(
|
|
180
|
-
self, implicit_comment: ImplicitComment, library: Library
|
|
181
|
-
) -> Union[Block, Collection[Block], None]:
|
|
182
|
-
"""Transform an implicit comment. Called by `transform_block` if the block is an implicit comment.
|
|
183
|
-
|
|
184
|
-
Note: This method modifies the passed implicit comment. For a method
|
|
185
|
-
respecting the `allow_inplace_modification` property,
|
|
186
|
-
you should use `transform` or `transform_block` instead.
|
|
187
|
-
"""
|
|
188
|
-
return implicit_comment
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
class LibraryMiddleware(Middleware, abc.ABC):
|
|
192
|
-
"""Changes an overall library at once (not just on a per-block basis).
|
|
193
|
-
|
|
194
|
-
Examples of library-wide changes are:
|
|
195
|
-
- Re-Sorting the blocks in the library.
|
|
196
|
-
- Transforming the library instance to a custom subclass of Library.
|
|
197
|
-
|
|
198
|
-
Whatever can be done in a BlockMiddleware, should be done
|
|
199
|
-
in a BlockMiddleware (and not in a LibraryMiddleware),
|
|
200
|
-
for performance reasons (e.g. deleting blocks, ...).
|
|
201
|
-
"""
|
|
202
|
-
|
|
203
|
-
def __init__(self, allow_inplace_modification: bool = True):
|
|
204
|
-
# As library middleware is run per library (not per block individually),
|
|
205
|
-
# it cannot be parallelized.
|
|
206
|
-
super().__init__(
|
|
207
|
-
allow_inplace_modification=allow_inplace_modification,
|
|
208
|
-
allow_parallel_execution=False,
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
def transform(self, library: Library) -> Library:
|
|
212
|
-
"""Transform a library.
|
|
213
|
-
|
|
214
|
-
:param library: Library to transform.
|
|
215
|
-
:return: Transformed library. If the library should not be modified,
|
|
216
|
-
return a copy of the original library.
|
|
217
|
-
The returned library has to be a new instance, except if
|
|
218
|
-
`self.allow_inplace_modification` is True (in which case the library
|
|
219
|
-
may also return the original library).
|
|
220
|
-
"""
|
|
221
|
-
library = library if self.allow_inplace_modification else deepcopy(library)
|
|
222
|
-
return library
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
from .middleware import Middleware
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def default_parse_stack(allow_inplace_modification: bool = True) -> List[Middleware]:
|
|
7
|
-
"""Give the default parse stack to be applied after splitting, if not specified otherwise."""
|
|
8
|
-
return []
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def default_unparse_stack(allow_inplace_modification: bool = False) -> List[Middleware]:
|
|
12
|
-
"""Give the default unparse stack to be applied before writing, if not specified otherwise."""
|
|
13
|
-
return []
|