wexample-wex-addon-dev-python 0.0.61__py3-none-any.whl → 0.0.63__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.
- wexample_wex_addon_dev_python/config_value/python_package_readme_config_value.py +27 -226
- wexample_wex_addon_dev_python/const/python.py +0 -0
- wexample_wex_addon_dev_python/file/python_app_iml_file.py +41 -0
- wexample_wex_addon_dev_python/file/{python_package_toml_file.py → python_pyproject_toml_file.py} +60 -77
- wexample_wex_addon_dev_python/resources/__init__.py +0 -0
- wexample_wex_addon_dev_python/resources/readme_templates/__init__.py +0 -0
- wexample_wex_addon_dev_python/resources/readme_templates/tests.md.j2 +0 -0
- wexample_wex_addon_dev_python/workdir/python_package_workdir.py +90 -220
- wexample_wex_addon_dev_python/workdir/python_packages_suite_workdir.py +0 -88
- wexample_wex_addon_dev_python/workdir/python_workdir.py +63 -67
- {wexample_wex_addon_dev_python-0.0.61.dist-info → wexample_wex_addon_dev_python-0.0.63.dist-info}/METADATA +73 -15
- {wexample_wex_addon_dev_python-0.0.61.dist-info → wexample_wex_addon_dev_python-0.0.63.dist-info}/RECORD +10 -10
- wexample_wex_addon_dev_python/resources/readme_templates/title.md.j2 +0 -5
- {wexample_wex_addon_dev_python-0.0.61.dist-info → wexample_wex_addon_dev_python-0.0.63.dist-info}/WHEEL +0 -0
- {wexample_wex_addon_dev_python-0.0.61.dist-info → wexample_wex_addon_dev_python-0.0.63.dist-info}/entry_points.txt +0 -0
|
@@ -2,248 +2,49 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
-
from wexample_filestate.config_value.readme_content_config_value import (
|
|
6
|
-
ReadmeContentConfigValue,
|
|
7
|
-
)
|
|
8
|
-
from wexample_helpers.classes.field import public_field
|
|
9
5
|
from wexample_helpers.decorator.base_class import base_class
|
|
6
|
+
from wexample_wex_addon_app.config_value.app_readme_config_value import (
|
|
7
|
+
AppReadmeConfigValue,
|
|
8
|
+
)
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
12
|
-
|
|
13
|
-
PythonPackageWorkdir,
|
|
14
|
-
)
|
|
11
|
+
pass
|
|
15
12
|
|
|
16
13
|
|
|
17
14
|
@base_class
|
|
18
|
-
class PythonPackageReadmeContentConfigValue(
|
|
19
|
-
|
|
20
|
-
description="The python package workdir"
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
def get_templates(self) -> list[str] | None:
|
|
24
|
-
# Prepare context for Jinja2 rendering
|
|
25
|
-
context = self._get_template_context()
|
|
26
|
-
|
|
27
|
-
# Define fixed order of README sections
|
|
28
|
-
section_names = [
|
|
29
|
-
"title",
|
|
30
|
-
"table-of-contents",
|
|
31
|
-
"status-compatibility",
|
|
32
|
-
"prerequisites",
|
|
33
|
-
"installation",
|
|
34
|
-
"quickstart",
|
|
35
|
-
"basic-usage",
|
|
36
|
-
"configuration",
|
|
37
|
-
"logging",
|
|
38
|
-
"api-reference",
|
|
39
|
-
"examples",
|
|
40
|
-
"tests",
|
|
41
|
-
"code-quality",
|
|
42
|
-
"versioning",
|
|
43
|
-
"changelog",
|
|
44
|
-
"migration-notes",
|
|
45
|
-
"roadmap",
|
|
46
|
-
"troubleshooting",
|
|
47
|
-
"security",
|
|
48
|
-
"privacy",
|
|
49
|
-
"support",
|
|
50
|
-
"contribution-guidelines",
|
|
51
|
-
"maintainers",
|
|
52
|
-
"license",
|
|
53
|
-
"useful-links",
|
|
54
|
-
"suite-integration",
|
|
55
|
-
"compatibility-matrix",
|
|
56
|
-
"requirements",
|
|
57
|
-
"dependencies",
|
|
58
|
-
"links",
|
|
59
|
-
"suite-signature",
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
# First pass: collect available sections (excluding title and table-of-contents)
|
|
63
|
-
available_sections = []
|
|
64
|
-
for section_name in section_names:
|
|
65
|
-
if section_name not in ["title", "table-of-contents"]:
|
|
66
|
-
# Check if section exists
|
|
67
|
-
if self._section_exists(section_name):
|
|
68
|
-
available_sections.append(
|
|
69
|
-
{
|
|
70
|
-
"name": section_name,
|
|
71
|
-
"title": self._section_name_to_title(section_name),
|
|
72
|
-
"anchor": section_name.replace("_", "-"),
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
# Add available sections to context for table-of-contents
|
|
77
|
-
context["available_sections"] = available_sections
|
|
15
|
+
class PythonPackageReadmeContentConfigValue(AppReadmeConfigValue):
|
|
16
|
+
"""README generation for Python packages."""
|
|
78
17
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
section_content = self._render_readme_section(section_name, context)
|
|
83
|
-
if section_content:
|
|
84
|
-
rendered_content += f"{section_content}\n\n"
|
|
18
|
+
def _get_app_description(self) -> str:
|
|
19
|
+
"""Extract description from pyproject.toml."""
|
|
20
|
+
return self.workdir.get_app_config().get("project", {}).get("description")
|
|
85
21
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# Use TOMLDocument from the workdir
|
|
90
|
-
doc = self.workdir.get_project_config()
|
|
91
|
-
project = doc.get("project", {}) if isinstance(doc, dict) else {}
|
|
92
|
-
|
|
93
|
-
# Extract information
|
|
94
|
-
description = project.get("description", "")
|
|
95
|
-
python_version = project.get("requires-python", "")
|
|
96
|
-
dependencies = project.get("dependencies", [])
|
|
22
|
+
def _get_app_homepage(self) -> str:
|
|
23
|
+
"""Extract homepage URL from pyproject.toml."""
|
|
24
|
+
project = self.workdir.get_app_config()
|
|
97
25
|
urls = (
|
|
98
26
|
project.get("urls", {}) if isinstance(project.get("urls", {}), dict) else {}
|
|
99
27
|
)
|
|
100
|
-
|
|
101
|
-
|
|
28
|
+
return urls.get("homepage") or urls.get("Homepage") or ""
|
|
29
|
+
|
|
30
|
+
def _get_project_license(self) -> str | None:
|
|
31
|
+
"""Extract license information from pyproject.toml."""
|
|
32
|
+
project = self.workdir.get_app_config()
|
|
102
33
|
license_field = project.get("license", {})
|
|
103
34
|
if isinstance(license_field, dict):
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)
|
|
107
|
-
else:
|
|
108
|
-
license_info = str(license_field) if license_field else ""
|
|
109
|
-
|
|
110
|
-
# Format dependencies list
|
|
111
|
-
deps_list = "\n".join([f"- {dep}" for dep in dependencies])
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
"package_name": self.workdir.get_package_name(),
|
|
115
|
-
"version": self.workdir.get_project_version(),
|
|
116
|
-
"description": description,
|
|
117
|
-
"python_version": python_version,
|
|
118
|
-
"dependencies": dependencies,
|
|
119
|
-
"deps_list": deps_list,
|
|
120
|
-
"homepage": homepage,
|
|
121
|
-
"license_info": license_info,
|
|
122
|
-
"workdir": self.workdir,
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
def _render_readme_section(self, section_name: str, context: dict) -> str | None:
|
|
126
|
-
"""
|
|
127
|
-
Render a README section from .md or .md.j2 file with Jinja2 support.
|
|
128
|
-
|
|
129
|
-
Searches in three levels (in order):
|
|
130
|
-
1. Package-level templates
|
|
131
|
-
2. Suite-level templates
|
|
132
|
-
3. Default templates (bundled with the module)
|
|
133
|
-
|
|
134
|
-
Tries .md.j2 first, then .md. Both formats support Jinja2 variables.
|
|
135
|
-
|
|
136
|
-
Args:
|
|
137
|
-
section_name: Name of the section (without extension)
|
|
138
|
-
context: Jinja2 context variables for rendering
|
|
139
|
-
|
|
140
|
-
Returns:
|
|
141
|
-
Rendered content or None if section file not found
|
|
142
|
-
"""
|
|
143
|
-
from pathlib import Path
|
|
144
|
-
|
|
145
|
-
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
|
|
146
|
-
from wexample_app.const.globals import WORKDIR_SETUP_DIR
|
|
147
|
-
|
|
148
|
-
workdir_path = self.workdir.get_path()
|
|
149
|
-
|
|
150
|
-
search_paths = [
|
|
151
|
-
workdir_path / WORKDIR_SETUP_DIR / "knowledge" / "readme", # Package-level
|
|
152
|
-
]
|
|
35
|
+
return license_field.get("text", "") or license_field.get("file", "")
|
|
36
|
+
return str(license_field) if license_field else ""
|
|
153
37
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if suite_path is not None:
|
|
157
|
-
search_paths.append(
|
|
158
|
-
suite_path
|
|
159
|
-
/ WORKDIR_SETUP_DIR
|
|
160
|
-
/ "knowledge"
|
|
161
|
-
/ "package-readme", # Suite-level
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
# Add default templates path (bundled with the module)
|
|
165
|
-
default_templates_path = (
|
|
166
|
-
Path(__file__).parent.parent / "resources" / "readme_templates"
|
|
167
|
-
)
|
|
168
|
-
search_paths.append(default_templates_path)
|
|
169
|
-
|
|
170
|
-
# Try .md.j2 first (Jinja2 template)
|
|
171
|
-
for search_path in search_paths:
|
|
172
|
-
if not search_path.exists():
|
|
173
|
-
continue
|
|
174
|
-
|
|
175
|
-
env = Environment(loader=FileSystemLoader(str(search_path)))
|
|
176
|
-
try:
|
|
177
|
-
template = env.get_template(f"{section_name}.md.j2")
|
|
178
|
-
return template.render(context)
|
|
179
|
-
except TemplateNotFound:
|
|
180
|
-
pass
|
|
181
|
-
|
|
182
|
-
# Try .md (static markdown, still rendered with Jinja2)
|
|
183
|
-
for search_path in search_paths:
|
|
184
|
-
md_path = search_path / f"{section_name}.md"
|
|
185
|
-
if md_path.exists():
|
|
186
|
-
content = md_path.read_text(encoding="utf-8")
|
|
187
|
-
env = Environment(loader=FileSystemLoader(str(search_path)))
|
|
188
|
-
template = env.from_string(content)
|
|
189
|
-
return template.render(context)
|
|
190
|
-
|
|
191
|
-
return None
|
|
192
|
-
|
|
193
|
-
def _section_exists(self, section_name: str) -> bool:
|
|
194
|
-
"""
|
|
195
|
-
Check if a section file exists (.md or .md.j2).
|
|
196
|
-
|
|
197
|
-
Searches in three levels:
|
|
198
|
-
1. Package-level templates
|
|
199
|
-
2. Suite-level templates
|
|
200
|
-
3. Default templates (bundled with the module)
|
|
201
|
-
|
|
202
|
-
Args:
|
|
203
|
-
section_name: Name of the section (without extension)
|
|
38
|
+
def _get_template_context(self) -> dict:
|
|
39
|
+
"""Build template context with Python-specific variables.
|
|
204
40
|
|
|
205
|
-
|
|
206
|
-
True if section file exists, False otherwise
|
|
41
|
+
Adds python_version to the base context.
|
|
207
42
|
"""
|
|
208
|
-
|
|
43
|
+
context = super()._get_template_context()
|
|
209
44
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
search_paths = [
|
|
215
|
-
workdir_path / WORKDIR_SETUP_DIR / "knowledge" / "readme",
|
|
216
|
-
]
|
|
217
|
-
|
|
218
|
-
# Package may have a suite.
|
|
219
|
-
suite_path = self.workdir.find_suite_workdir_path()
|
|
220
|
-
if suite_path is not None:
|
|
221
|
-
search_paths.append(
|
|
222
|
-
suite_path / WORKDIR_SETUP_DIR / "knowledge" / "package-readme",
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
# Add default templates path (bundled with the module)
|
|
226
|
-
default_templates_path = (
|
|
227
|
-
Path(__file__).parent.parent / "resources" / "readme_templates"
|
|
45
|
+
# Add Python-specific variable
|
|
46
|
+
context["python_version"] = (
|
|
47
|
+
self.workdir.get_app_config().get("project", {}).get("requires-python", "")
|
|
228
48
|
)
|
|
229
|
-
search_paths.append(default_templates_path)
|
|
230
|
-
|
|
231
|
-
for search_path in search_paths:
|
|
232
|
-
if (search_path / f"{section_name}.md.j2").exists():
|
|
233
|
-
return True
|
|
234
|
-
if (search_path / f"{section_name}.md").exists():
|
|
235
|
-
return True
|
|
236
49
|
|
|
237
|
-
return
|
|
238
|
-
|
|
239
|
-
def _section_name_to_title(self, section_name: str) -> str:
|
|
240
|
-
"""
|
|
241
|
-
Convert section name to human-readable title.
|
|
242
|
-
|
|
243
|
-
Args:
|
|
244
|
-
section_name: Section name (e.g., "basic-usage")
|
|
245
|
-
|
|
246
|
-
Returns:
|
|
247
|
-
Human-readable title (e.g., "Basic Usage")
|
|
248
|
-
"""
|
|
249
|
-
return section_name.replace("-", " ").replace("_", " ").title()
|
|
50
|
+
return context
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import Any, ClassVar
|
|
5
|
+
|
|
6
|
+
from wexample_app.item.file.iml_file import ImlFile
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PythonAppImlFile(ImlFile):
|
|
10
|
+
"""
|
|
11
|
+
IntelliJ IDEA .iml helper tailored for Python apps (src/tests layout, python module type).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
MODULE_TYPE: ClassVar[str] = "PYTHON_MODULE"
|
|
15
|
+
|
|
16
|
+
def _default_exclude_folders(self) -> Iterable[dict[str, Any]]:
|
|
17
|
+
return (
|
|
18
|
+
{
|
|
19
|
+
"@url": f"{self.MODULE_DIR_URL}/dist",
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def _default_module_attributes(self) -> dict[str, str]:
|
|
24
|
+
attrs = super()._default_module_attributes()
|
|
25
|
+
attrs.setdefault("@type", self.MODULE_TYPE)
|
|
26
|
+
return attrs
|
|
27
|
+
|
|
28
|
+
def _default_order_entries(self) -> Iterable[dict[str, Any]]:
|
|
29
|
+
return ({"@type": "sourceFolder", "@forTests": "false"},)
|
|
30
|
+
|
|
31
|
+
def _default_source_folders(self) -> Iterable[dict[str, Any]]:
|
|
32
|
+
return (
|
|
33
|
+
{
|
|
34
|
+
"@url": f"{self.MODULE_DIR_URL}/src",
|
|
35
|
+
"@isTestSource": "false",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"@url": f"{self.MODULE_DIR_URL}/tests",
|
|
39
|
+
"@isTestSource": "true",
|
|
40
|
+
},
|
|
41
|
+
)
|
wexample_wex_addon_dev_python/file/{python_package_toml_file.py → python_pyproject_toml_file.py}
RENAMED
|
@@ -8,35 +8,47 @@ from wexample_wex_addon_app.const.path import APP_PATH_README
|
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from tomlkit import TOMLDocument
|
|
11
|
-
from wexample_wex_addon_app.workdir.code_base_workdir import (
|
|
12
|
-
CodeBaseWorkdir,
|
|
13
|
-
)
|
|
14
11
|
|
|
15
12
|
|
|
16
13
|
@base_class
|
|
17
|
-
class
|
|
14
|
+
class PythonPyprojectTomlFile(TomlFile):
|
|
18
15
|
def add_dependency(
|
|
19
|
-
self,
|
|
16
|
+
self,
|
|
17
|
+
package_name: str,
|
|
18
|
+
version: str,
|
|
19
|
+
operator: str = "==",
|
|
20
|
+
optional: bool = False,
|
|
21
|
+
group: None | str = None,
|
|
20
22
|
) -> bool:
|
|
21
23
|
from packaging.requirements import Requirement
|
|
22
24
|
from packaging.utils import canonicalize_name
|
|
23
25
|
from wexample_filestate_python.helpers.toml import toml_sort_string_array
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
spec = f"{package_name}{operator}{version}"
|
|
26
28
|
new_req = Requirement(spec)
|
|
27
29
|
new_name = canonicalize_name(new_req.name)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
for dep in deps:
|
|
31
|
-
if canonicalize_name(Requirement(dep).name) == new_name:
|
|
32
|
-
old_spec = dep
|
|
33
|
-
break
|
|
31
|
+
deps = self._get_deps_array(optional=optional, group=group)
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
# Look for existing dependency
|
|
34
|
+
old_spec = next(
|
|
35
|
+
(d for d in deps if canonicalize_name(Requirement(d).name) == new_name),
|
|
36
|
+
None,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Remove old dep if exists
|
|
40
|
+
if old_spec:
|
|
41
|
+
deps.remove(old_spec)
|
|
36
42
|
|
|
43
|
+
# Add new version
|
|
37
44
|
deps.append(spec)
|
|
45
|
+
|
|
46
|
+
# Sort array
|
|
38
47
|
toml_sort_string_array(deps)
|
|
39
48
|
|
|
49
|
+
# Save file
|
|
50
|
+
self.write_parsed()
|
|
51
|
+
|
|
40
52
|
return old_spec != spec
|
|
41
53
|
|
|
42
54
|
def dumps(self, content: TOMLDocument | dict | None = None) -> str:
|
|
@@ -47,10 +59,10 @@ class PythonPackageTomlFile(TomlFile):
|
|
|
47
59
|
|
|
48
60
|
content = content or self.read_parsed()
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
import_name =
|
|
52
|
-
project_name =
|
|
53
|
-
project_version =
|
|
62
|
+
workdir = self.get_parent_item()
|
|
63
|
+
import_name = workdir.get_package_import_name()
|
|
64
|
+
project_name = workdir.get_package_name()
|
|
65
|
+
project_version = workdir.get_project_version()
|
|
54
66
|
|
|
55
67
|
self._enforce_build_system(content)
|
|
56
68
|
self._enforce_pdm_build(content, import_name)
|
|
@@ -65,40 +77,21 @@ class PythonPackageTomlFile(TomlFile):
|
|
|
65
77
|
|
|
66
78
|
return result
|
|
67
79
|
|
|
68
|
-
def
|
|
69
|
-
from wexample_wex_addon_app.workdir.code_base_workdir import CodeBaseWorkdir
|
|
70
|
-
|
|
71
|
-
return self.find_closest(CodeBaseWorkdir)
|
|
72
|
-
|
|
73
|
-
def list_dependencies(
|
|
80
|
+
def get_dependencies_versions(
|
|
74
81
|
self, optional: bool = False, group: str = "dev"
|
|
75
|
-
) ->
|
|
76
|
-
deps = self._get_deps_array(optional=optional, group=group)
|
|
77
|
-
return [str(x) for x in list(deps)]
|
|
78
|
-
|
|
79
|
-
def list_dependency_names(
|
|
80
|
-
self,
|
|
81
|
-
canonicalize_names: bool = True,
|
|
82
|
-
optional: bool = False,
|
|
83
|
-
group: str = "dev",
|
|
84
|
-
) -> list[str]:
|
|
85
|
-
"""Return dependency package names derived from list_dependencies().
|
|
86
|
-
|
|
87
|
-
If canonicalize_names is True, names are normalized using packaging's
|
|
88
|
-
canonicalize_name for robust comparisons (dash/underscore, case, etc.).
|
|
89
|
-
"""
|
|
82
|
+
) -> dict[str, str]:
|
|
90
83
|
from packaging.requirements import Requirement
|
|
91
84
|
from packaging.utils import canonicalize_name
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return
|
|
86
|
+
deps = self._get_deps_array(optional=optional, group=group)
|
|
87
|
+
|
|
88
|
+
map = {}
|
|
89
|
+
for spec in list(deps):
|
|
90
|
+
req = Requirement(spec)
|
|
91
|
+
# name: version
|
|
92
|
+
map[canonicalize_name(req.name)] = str(req.specifier)
|
|
93
|
+
|
|
94
|
+
return map
|
|
102
95
|
|
|
103
96
|
def optional_group_array(self, group: str):
|
|
104
97
|
"""Ensure and return project.optional-dependencies[group] as multi-line array."""
|
|
@@ -197,34 +190,28 @@ class PythonPackageTomlFile(TomlFile):
|
|
|
197
190
|
project_tbl["requires-python"] = ">=3.10"
|
|
198
191
|
|
|
199
192
|
# Add description if available
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
project_tbl["description"] = description.get_str()
|
|
193
|
+
workdir = self.get_parent_item()
|
|
194
|
+
description = workdir.get_config().search("global.description")
|
|
195
|
+
if not description.is_none():
|
|
196
|
+
project_tbl["description"] = description.get_str()
|
|
205
197
|
|
|
206
198
|
# Add authors if available
|
|
207
|
-
|
|
208
|
-
from tomlkit import array, inline_table
|
|
199
|
+
from tomlkit import array, inline_table
|
|
209
200
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
)
|
|
213
|
-
author_email = package.search_in_package_or_suite_config(
|
|
214
|
-
"global.authors.email"
|
|
215
|
-
)
|
|
201
|
+
author_name = workdir.search_in_package_or_suite_config("global.authors.name")
|
|
202
|
+
author_email = workdir.search_in_package_or_suite_config("global.authors.email")
|
|
216
203
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
204
|
+
if not author_name.is_none() or not author_email.is_none():
|
|
205
|
+
authors_arr = array()
|
|
206
|
+
author_tbl = inline_table()
|
|
220
207
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
208
|
+
if not author_name.is_none():
|
|
209
|
+
author_tbl["name"] = author_name.get_str()
|
|
210
|
+
if not author_email.is_none():
|
|
211
|
+
author_tbl["email"] = author_email.get_str()
|
|
225
212
|
|
|
226
|
-
|
|
227
|
-
|
|
213
|
+
authors_arr.append(author_tbl)
|
|
214
|
+
project_tbl["authors"] = authors_arr
|
|
228
215
|
|
|
229
216
|
# Add classifiers (standard Python package metadata)
|
|
230
217
|
project_tbl["classifiers"] = [
|
|
@@ -234,14 +221,11 @@ class PythonPackageTomlFile(TomlFile):
|
|
|
234
221
|
]
|
|
235
222
|
|
|
236
223
|
# Add README if it exists
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
readme_tbl, _ = toml_ensure_table(project_tbl, ["readme"])
|
|
243
|
-
readme_tbl["file"] = str(APP_PATH_README)
|
|
244
|
-
readme_tbl["content-type"] = "text/markdown"
|
|
224
|
+
readme_file = workdir.find_by_name(APP_PATH_README)
|
|
225
|
+
if readme_file:
|
|
226
|
+
readme_tbl, _ = toml_ensure_table(project_tbl, ["readme"])
|
|
227
|
+
readme_tbl["file"] = str(APP_PATH_README)
|
|
228
|
+
readme_tbl["content-type"] = "text/markdown"
|
|
245
229
|
|
|
246
230
|
# Add MIT license
|
|
247
231
|
license_tbl, _ = toml_ensure_table(project_tbl, ["license"])
|
|
@@ -305,7 +289,6 @@ class PythonPackageTomlFile(TomlFile):
|
|
|
305
289
|
|
|
306
290
|
toml_sort_string_array(dev_arr)
|
|
307
291
|
|
|
308
|
-
# --- Unified dependency accessors (runtime vs optional) ---
|
|
309
292
|
def _get_deps_array(self, optional: bool = False, group: str = "dev"):
|
|
310
293
|
"""Return TOML array for runtime deps or optional group (multiline)."""
|
|
311
294
|
return (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|