-
Notifications
You must be signed in to change notification settings - Fork 0
/
packager_files.py
161 lines (123 loc) · 6.35 KB
/
packager_files.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from generallibrary import CodeLine, current_datetime, Markdown
from generalfile import Path
from generalpackager import LocalRepo
class GenerateFile:
""" Handle generation of files. """
def __init__(self, path, text_func, packager, aesthetic):
self.text_func = text_func
self.packager = packager
self.aesthetic = aesthetic
self.relative_path = path.relative(base=packager.path)
self.path = packager.path / self.relative_path
def generate(self):
""" Generate actual file. """
self.path.text.write(f"{self.text_func()}\n", overwrite=True)
class _PackagerFiles:
""" Generates setup, license and gitexclude. """
def __init_post__(self):
""" Todo: Watermark generated files to prevent mistake of thinking you can modify them directly.
:param generalpackager.Packager self: """
self.file_setup = GenerateFile(self.localrepo.get_setup_path(), self.generate_setup, self, aesthetic=False)
self.file_git_exclude = GenerateFile(self.localrepo.get_git_exclude_path(), self.generate_git_exclude, self, aesthetic=True)
self.file_license = GenerateFile(self.localrepo.get_license_path(), self.generate_license, self, aesthetic=True)
self.file_workflow = GenerateFile(self.localrepo.get_workflow_path(), self.generate_workflow, self, aesthetic=True)
self.file_readme = GenerateFile(self.localrepo.get_readme_path(), self.generate_readme, self, aesthetic=True)
self.files = [getattr(self, key) for key in dir(self) if key.startswith("file_")]
self.files_by_relative_path = {file.relative_path: file for file in self.files}
def get_changed_files(self, aesthetic=True):
""" Get a list of changed files compared to remote with optional aesthetic files.
:param generalpackager.Packager self:
:param aesthetic: """
changed_files = []
for relative_path in self.localrepo.get_changed_files():
if not aesthetic and getattr(self.files_by_relative_path.get(relative_path, None), "aesthetic", False):
continue
changed_files.append(relative_path)
return changed_files
def generate_setup(self):
""" Generate setup.py.
:param generalpackager.Packager self: """
readme_path = self.localrepo.get_readme_path().relative(self.localrepo.get_setup_path().get_parent())
last_version_split = self.python[-1].split(".")
last_version_bumped_micro = f"{last_version_split[0]}.{int(last_version_split[1]) + 1}"
setup_kwargs = {
"name": f'"{self.localrepo.name}"',
"author": f"'{self.author}'",
"author_email": f'"{self.email}"',
"version": f'"{self.localrepo.version}"',
"description": f'"{self.localrepo.description}"',
"long_description": f"(Path(__file__).parent / '{readme_path}').read_text(encoding='utf-8')",
"long_description_content_type": '"text/markdown"',
"install_requires": self.localrepo.install_requires,
"url": f'"{self.github.url}"',
"license": f'"{self.license}"',
"python_requires": f'">={self.python[0]}, <{last_version_bumped_micro}"',
"packages": 'find_namespace_packages(exclude=("build*", "dist*"))',
"extras_require": self.localrepo.extras_require,
"classifiers": self.get_classifiers(),
}
top = CodeLine()
top.add(CodeLine("from setuptools import setup, find_namespace_packages", space_before=1))
top.add(CodeLine("from pathlib import Path", space_after=1))
setup = top.add(CodeLine("setup("))
for key, value in setup_kwargs.items():
if isinstance(value, list) and value:
list_ = setup.add(CodeLine(f"{key}=["))
for item in value:
list_.add(CodeLine(f"'{item}',"))
setup.add(CodeLine("],"))
elif isinstance(value, dict) and value:
dict_ = setup.add(CodeLine(f"{key}={{"))
for k, v in value.items():
dict_.add(CodeLine(f"'{k}': {v},"))
setup.add(CodeLine("},"))
else:
setup.add(CodeLine(f"{key}={value},"))
top.add(CodeLine(")"))
return top.text()
def generate_git_exclude(self):
""" Generate git exclude file.
:param generalpackager.Packager self: """
return "\n".join(self.git_exclude_lines)
def generate_license(self):
""" Generate LICENSE by using Packager.license.
:param generalpackager.Packager self: """
text = Path(self.repos_path / f"generalpackager/generalpackager/licenses/{self.license}").text.read()
assert "$" in text
text = text.replace("$year", str(current_datetime().year))
text = text.replace("$author", self.author)
assert "$" not in text
return text
def generate_workflow(self):
""" Generate workflow.yml.
:param generalpackager.Packager self: """
workflow = CodeLine()
workflow.indent_str = " " * 2
workflow.add("name: workflow")
workflow.add(self.get_triggers())
jobs = workflow.add("jobs:")
jobs.add(self.get_unittest_job())
jobs.add(self.get_sync_job())
return workflow.text()
def generate_readme(self):
""" Generate readme markdown and overwrite README.md in local repo.
:param generalpackager.Packager self: """
# Description
markdown = Markdown(self.localrepo.description, header=f"{self.name} {self.localrepo.version}")
# Badges
markdown.add_lines(*self.get_badges_dict().values())
# Table of contents - Placeholder
contents = Markdown(header="Contents", parent=markdown)
# Installation
self.get_installation_markdown().set_parent(parent=markdown)
# Attributes
self.get_attributes_markdown().set_parent(parent=markdown)
# Todos
todos = self.localrepo.get_todos()
if todos:
Markdown(header="Todo", parent=markdown).add_table_lines(*todos)
# Table of contents - Configuration
self.configure_contents_markdown(markdown=contents)
# Footnote
self.get_footnote_markdown().set_parent(parent=markdown)
return markdown