Skip to content

Commit d762adc

Browse files
committed
pdm init command
1 parent b1ab768 commit d762adc

10 files changed

+106
-28
lines changed

pdm/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.2"
1+
__version__ = "0.0.3"

pdm/cli/actions.py

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import itertools
2+
import shutil
23
from typing import Dict, Iterable, Optional, Sequence
34

45
import halo
@@ -292,16 +293,53 @@ def do_list(project: Project) -> None:
292293

293294

294295
def do_build(
295-
project: Project, sdist: bool = True, wheel: bool = True, dest: str = "dist"
296+
project: Project,
297+
sdist: bool = True,
298+
wheel: bool = True,
299+
dest: str = "dist",
300+
clean: bool = True,
296301
):
297302
if not wheel and not sdist:
298303
context.io.echo("All artifacts are disabled, nothing to do.")
299304
return
300305
ireq = project.make_self_candidate(False).ireq
301306
ireq.source_dir = "."
307+
if clean:
308+
shutil.rmtree(dest, ignore_errors=True)
302309
if sdist:
303310
with SdistBuilder(ireq) as builder:
304311
builder.build(dest)
305312
if wheel:
306313
with WheelBuilder(ireq) as builder:
307314
builder.build(dest)
315+
316+
317+
def do_init(
318+
project: Project,
319+
name: str = "",
320+
version: str = "",
321+
license: str = "MIT",
322+
author: str = "",
323+
email: str = "",
324+
) -> None:
325+
data = {
326+
"tool": {
327+
"pdm": {
328+
"name": name,
329+
"version": version,
330+
"description": "",
331+
"author": f"{author} <{email}>",
332+
"license": license,
333+
"homepage": "",
334+
"dependencies": tomlkit.table(),
335+
"dev-dependencies": tomlkit.table(),
336+
}
337+
},
338+
"build-system": {"requires": "pdm", "build-backend": "pdm.builders.api"},
339+
}
340+
if not project.pyproject:
341+
project._pyproject = data
342+
else:
343+
project._pyproject.setdefault("tool", {})["pdm"] = data["tool"]["pdm"]
344+
project._pyproject["build-system"] = data["build-system"]
345+
project.write_pyproject()

pdm/cli/commands.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from pdm.context import context
1818
from pdm.exceptions import CommandNotFound
1919
from pdm.project import Project
20+
from pdm.utils import get_user_email_from_git
2021

2122
pass_project = click.make_pass_decorator(Project, ensure=True)
2223
context_settings = {"ignore_unknown_options": True, "allow_extra_args": True}
@@ -213,6 +214,36 @@ def list_(project):
213214
"--no-wheel", "wheel", default=True, flag_value=False, help="Don't build wheels."
214215
)
215216
@click.option("-d", "--dest", default="dist", help="Target directory to put artifacts.")
217+
@click.option(
218+
"--no-clean",
219+
"clean",
220+
default=True,
221+
flag_value=False,
222+
help="Do not clean the target directory.",
223+
)
224+
@pass_project
225+
def build(project, sdist, wheel, dest, clean):
226+
actions.do_build(project, sdist, wheel, dest, clean)
227+
228+
229+
@cli.command(help="Initialize a pyproject.toml for PDM.")
216230
@pass_project
217-
def build(project, sdist, wheel, dest):
218-
actions.do_build(project, sdist, wheel, dest)
231+
def init(project):
232+
if project.pyproject_file.exists():
233+
context.io.echo(
234+
"{}".format(
235+
context.io.cyan("pyproject.toml already exists, update it now.")
236+
)
237+
)
238+
else:
239+
context.io.echo(
240+
"{}".format(context.io.cyan("Creating a pyproject.toml for PDM..."))
241+
)
242+
name = click.prompt(f"Project name", default=project.root.name)
243+
version = click.prompt("Project version", default="0.0.0")
244+
license = click.prompt("License(SPDX name)", default="MIT")
245+
246+
git_user, git_email = get_user_email_from_git()
247+
author = click.prompt(f"Author name", default=git_user)
248+
email = click.prompt(f"Author email", default=git_email)
249+
actions.do_init(project, name, version, license, author, email)

pdm/installers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def compare_with_working_set(self) -> Tuple[List[str], List[str], List[str]]:
131131
dist = working_set[key][0]
132132
if can.marker and not can.marker.evaluate(environment):
133133
to_remove.append(key)
134-
elif _is_dist_editable(dist) or dist.version != can.version:
134+
elif not _is_dist_editable(dist) and dist.version != can.version:
135135
# XXX: An editable distribution is always considered as consistent.
136136
to_update.append(key)
137137
to_add = list(

pdm/project/core.py

+2-17
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def __repr__(self) -> str:
7777
@property
7878
def pyproject(self):
7979
# type: () -> Container
80-
if not self._pyproject:
80+
if not self._pyproject and self.pyproject_file.exists():
8181
data = tomlkit.parse(self.pyproject_file.read_text("utf-8"))
8282
self._pyproject = data
8383
return self._pyproject
@@ -197,7 +197,7 @@ def write_lockfile(self, toml_data: Container, show_message: bool = True) -> Non
197197
self._lockfile = None
198198

199199
def make_self_candidate(self, editable: bool = True) -> Candidate:
200-
req = parse_requirement(".", editable)
200+
req = parse_requirement(self.root.as_posix(), editable)
201201
req.name = self.meta.name
202202
return Candidate(
203203
req, self.environment, name=self.meta.name, version=self.meta.version
@@ -283,21 +283,6 @@ def write_pyproject(self, show_message: bool = True) -> None:
283283
context.io.echo("Changes are written to pyproject.toml.")
284284
self._pyproject = None
285285

286-
def init_pyproject(self) -> None:
287-
if not self._pyproject:
288-
self._pyproject = {}
289-
self._pyproject.update(
290-
{
291-
"tool": {
292-
"pdm": {
293-
"dependencies": tomlkit.table(),
294-
"dev-dependencies": tomlkit.table(),
295-
}
296-
}
297-
}
298-
)
299-
self.write_pyproject()
300-
301286
@property
302287
@pyproject_cache
303288
def meta(self) -> PackageMeta:

pdm/ui.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, verbosity: int = NORMAL, disable_colors: bool = False) -> Non
2121
setattr(self, color, functools.partial(self._style, fg=color))
2222

2323
def disable(self) -> None:
24-
self.disable_colors = False
24+
self.disable_colors = True
2525

2626
def set_verbosity(self, verbosity: int) -> None:
2727
self.verbosity = verbosity

pdm/utils.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -329,17 +329,39 @@ def get_pep508_environment(executable: str) -> Dict[str, Any]:
329329
return json.loads(subprocess.check_output(args))
330330

331331

332-
def convert_hashes(hases: Dict[str, str]) -> Dict[str, List[str]]:
332+
def convert_hashes(hashes: Dict[str, str]) -> Dict[str, List[str]]:
333333
"""Convert Pipfile.lock hash lines into InstallRequirement option format.
334334
335335
The option format uses a str-list mapping. Keys are hash algorithms, and
336336
the list contains all values of that algorithm.
337337
"""
338338
result = {}
339-
for hash_value in hases.values():
339+
for hash_value in hashes.values():
340340
try:
341341
name, hash_value = hash_value.split(":")
342342
except ValueError:
343343
name = "sha256"
344344
result.setdefault(name, []).append(hash_value)
345345
return result
346+
347+
348+
def get_user_email_from_git() -> Tuple[str, str]:
349+
"""Get username and email from git config.
350+
Return empty if not configured or git is not found.
351+
"""
352+
git = shutil.which("git")
353+
if not git:
354+
return "", ""
355+
try:
356+
username = subprocess.check_output(
357+
[git, "config", "user.name"], text=True
358+
).strip()
359+
except subprocess.CalledProcessError:
360+
username = ""
361+
try:
362+
email = subprocess.check_output(
363+
[git, "config", "user.email"], text=True
364+
).strip()
365+
except subprocess.CalledProcessError:
366+
email = ""
367+
return username, email

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.pdm]
22
name = "pdm"
3-
version = "0.0.2"
3+
version = "0.0.3"
44
description = "Python Development Master"
55
author = "frostming <[email protected]>"
66
license = "MIT"

tests/cli/test_actions.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ def test_sync_only_different(project, repository, synchronizer, capsys):
2424
)
2525
do_add(project, packages=["requests"])
2626
out, _ = capsys.readouterr()
27-
assert "3 packages added" in out
27+
assert "4 packages added" in out
2828
assert "1 package updated" in out
2929
assert "foo" in synchronizer.working_set
30+
assert "test-project" in synchronizer.working_set
3031
assert synchronizer.working_set["chardet"] == "3.0.4"
3132

3233

tests/conftest.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import pytest
1414

15+
from pdm.cli.actions import do_init
1516
from pdm.context import context
1617
from pdm.exceptions import CandidateInfoNotFound
1718
from pdm.installers import Synchronizer
@@ -210,7 +211,7 @@ def project(tmp_path, mocker):
210211
mocker.patch("pdm.utils.get_finder", get_local_finder)
211212
mocker.patch("pdm.models.environment.get_finder", get_local_finder)
212213
mocker.patch("pdm.cli.commands.Project", return_value=p)
213-
p.init_pyproject()
214+
do_init(p, "test_project", "0.0.0")
214215
return p
215216

216217

0 commit comments

Comments
 (0)