Code Monkey home page Code Monkey logo

copier-pdm's Introduction

pawamoy

about language music

πŸͺ Hello world

Hi, I'm TimothΓ©e Mazzucotelli. I develop open-source software, primarily Python tools and libraries. I do this full time: I earn my keep through sponsorships from individual users and companies, which is what makes these projects sustainable and gives you a chance to use them.

You can say hello to me on Mastodon, X, LinkedIn, Matrix, Discord, Telegram, Signal, or by email at [email protected] πŸ“« πŸ‘‹πŸΌ

🌱 Features

  • πŸŽ“ learned computer science at a french university
  • 🐍 about 10 years of experience in development, particularly with Python
  • 🎠 really enjoy sharing code and contributing to other projects
  • πŸ‘” working full time on open-source projects (following a sponsorware strategy)

🌲 Projects

πŸ“˜ Documentation πŸͺ› [Developer] tools #️⃣ Shell stuff
mkdocstrings griffe shellman
mkdocstrings-python aria2p shenv/shenv
mkdocstrings-shell πŸ”’ duty shellm-org/core
mkdocstrings-typescript πŸ”’ failprint shellm-org/cover
mkdocs-autorefs git-changelog shellm-org/daemon
mkdocs-coverage copier-uv shellm-org/debug
mkdocs-manpage copier-pdm shellm-org/format
mkdocs-spellcheck dependenpy shellm-org/loop
mkdocs-pygments πŸ”’ devboard πŸ”’ shellm-org/profiler
markdown-exec pypi-insiders πŸ”’ shellm-org/template
markdown-pycon πŸ”’ insiders-project πŸ”’ shellm-org/trace
happy-path πŸ”’

πŸ‹ See also

Have some green lemon:

green lemon

copier-pdm's People

Contributors

francisco-perez-sorrosal avatar laenan8466 avatar meramsey avatar pawamoy avatar victorbnl avatar whattheserver avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

copier-pdm's Issues

Prefix titles with Python version during multiruns

# duties.py
MULTIRUN = os.environ.get("MULTIRUN", "0") == "1"


def pyprefix(title: str) -> str:  # noqa: D103
    if MULTIRUN:
        prefix = f"(python{sys.version_info.major}.{sys.version_info.minor})"
        return f"{prefix:14}{title}"
    return title
# scripts/multirun.sh
export MULTIRUN=1

# TODO: remove echo statements

It then looks like:

% make check
> Currently selected Python version: python3.9
βœ“ (python3.7)   Checking code quality
βœ“ (python3.7)   Type-checking
βœ“ (python3.7)   Building documentation
βœ“ (python3.8)   Checking code quality
βœ“ (python3.8)   Type-checking
βœ“ (python3.8)   Building documentation
βœ“ (python3.9)   Checking code quality
βœ“ (python3.9)   Type-checking
βœ“ (python3.9)   Building documentation
βœ“ (python3.10)  Checking code quality
βœ“ (python3.10)  Type-checking
βœ“ (python3.10)  Building documentation
βœ“ (python3.11)  Checking code quality
βœ“ (python3.11)  Type-checking
βœ“ (python3.11)  Building documentation
> Restored previous Python version: python3.9
βœ“ Exporting dependencies as requirements
βœ“ Checking dependencies

or

% make test
βœ“ (python3.7)   Running tests
βœ“ (python3.8)   Running tests
βœ“ (python3.9)   Running tests
βœ“ (python3.10)  Running tests
βœ“ (python3.11)  Running tests

Credits/development: render a dependency graph

Following #4, I'd like to show a graph of dependencies (maybe just the runtime ones) in the credits or development page.
The data can be fetched from PDM's lock file again, and rendered using pydeps and markdown-exec.

feat: Devbox support

In devbox.json:

{
  "packages": [
    "pdm@latest"
  ],
  "shell": {
    "init_hook": []
  }
}

Update fails (unbound local error / subprocess error)

I just published version 0.8.0 which brings actual support for Copier v6. While there shouldn't be any issue when generating new projects and updating them, an issue can arise when you try to update a pre-existing project from pre 0.8.0 to 0.8.0+ while your installed Copier version is very recent, like 6.0.0a9. In that case, just downgrade your Copier version to 6.0.0a5 (maybe a6 and a7 work too, didn't try), run the update, and you can upgrade Copier again. In my case, I use pipx:

% copier -f update
...
UnboundLocalError: local variable 'use_precommit' referenced before assignment
...
subprocess.CalledProcessError: Command 'python scripts/post_generation.py' returned non-zero exit status 1.

% pipx install -f copier==6.0.0a0
% pipx inject copier 'markupsafe<2.1'
...
% copier -f -r 0.10.0 update
...  # OK
% pipx uninstall copier
% pipx install copier
...  # upgrade again to latest

The explanation is that since a7 or a8 (commit copier-org/copier@d86c88d), Copier stopped automatically setting the previous Jinja envops ([[, ]], [%, etc.) when _min_copier_version is not present in copier.yml. Copier does set these settings if you have _min_copier_version: 5.1.0 in copier.yml, which I didn't have. My bad for not catching it before!

/cc @yajo as it could be of interest to you πŸ™‚

"make format" and credits.md - changes affect mkdocs

Great repo, much less overhead than Hypermodem and cookiecutter.

Getting started with the repo and noticed that if a make format is done, it changes the docs/credits.md file contents which mkdocs then fails. In credits.md there is this (python exec="yes" on the open fence):

--8<-- "scripts/gen_credits.py"

which when make format is run with blacken-docs changes the format to:

--8 < --"scripts/gen_credits.py"

with spaces changes. make check-docs will then error with:

 WARNING -  markdown_exec: Execution of python code block exited with errors

  Code block is:

    --8 < --"scripts/gen_credits.py"

  Output is:

    Traceback (most recent call last):
...

I looked into duty and the lazy callable for blacken_docs has an exclude parameter, but it looks like it's never used. I'll continue to pursue there, but has anyone see this error and was able to correct?

"pdm run doc" fails

Thanks for sharing a great resource!

I have found an issue when using the command "pdm run doc"

> pdm run doc
INFO    -  Building documentation...
INFO    -  Cleaning site directory
../README.md ['C:\\Users\\Steve\\SynologyDrive\\development\\python\\test_app1\\docs']
ERROR   -  Error reading page 'index.md': Snippet at path '../README.md' could not be found

I believe this is caused by the nesting of the documentation folder "docs" inside a folder of the same name, and then attempting to reference README.md outside the root folder, docs.

The solution I have used is to update mkdocs.yml as follows

markdown_extensions:
  ...
  - pymdownx.snippets:
      check_paths: true
      restrict_base_path: false

I could create my 1st pull request if you would prefer that route.
Steve

Project idea: dependencies information getter

To help implementing #4, #5 and #6 without spaghetti code, maybe I should create a new project that reads PDM dependencies from both pyproject.toml and pdm.lock and queries various information from PyPI indexes or other online databases to extract as much information as possible about Python packages, and cache it locally (a given package's metadata never changes, supposedly).

Useful information:

  • name
  • summary
  • version
  • URLs
  • license (SPDX identifier?)
  • direct/indirect production dependency?
  • direct/indirect development dependency? (not mutually exclusive with production deps)
  • dependencies
  • parent dependencies if any (maybe hard to keep a clean cache)

A config file should also allow to add items manually, such as Python, PDM, safety and copier-pdm itself.

All these metadata could then be used to generate the credits file, check for dependency confusion, license compatibility issues, and even CVEs using safety/skjold.

double-quotes "pawamoy" not compatibile with win32

Issue on Windows

copier copy --trust "gh:pawamoy/copier-pdm" /path/to/your/new/project

results in invalid path 'project/docs/{% if author_username == "pawamoy" %}.overrides{% endif %}/main.html.jinja' .

 
Solved by
Changing "pawamoy" to 'pawamoy' in {% if author_username == "pawamoy" %}.overrides{% endif %}

 
as documented here: "On Windows, double-quotes are not valid characters in file and directory paths." Copier-docs

Thanks a lot for the great template πŸ™‚

Security: dependency confusion check

Add a duty that reads dependencies from pdm.lock and yields instance of a Dependency class which has an is_internal method that the user can override to implement their own logic (like checking if its name is in a set, or if it matches a regular expression). Then for every internal dependency, the duty asserts that it is absent from a given PyPI index (overridable as well). This way we ensure an internal dependency has no public counter-part that could lead to dependency confusion. Of course if public indexes are not reachable, the duty would be disabled.

Still not sure about implementing this though, as it is only useful in private contexts (which I have no interest in supporting in an opensource project).

Rewrite duties using callables rather than subprocesses

It is a bit more work, but we spare some resources and it should make things faster.

@duty
def check_quality(ctx, files=PY_SRC_LIST):
    """
    Check the code quality.

    Parameters:
        ctx: The context instance (passed automatically).
        files: The files to check.
    """
    from flake8.main.cli import main as flake8

    ctx.run(flake8, args=[["--config=config/flake8.ini", *files]], title="Checking code quality", pty=PTY)
@duty
def check_docs(ctx):
    """
    Check if the documentation builds correctly.

    Parameters:
        ctx: The context instance (passed automatically).
    """
    from mkdocs.__main__ import cli as mkdocs

    Path("htmlcov").mkdir(parents=True, exist_ok=True)
    Path("htmlcov/index.html").touch(exist_ok=True)
    ctx.run(mkdocs, args=[["build", "-s"]], title="Building documentation")
@duty  # noqa: WPS231
def check_types(ctx):  # noqa: WPS231
    """
    Check that the code is correctly typed.

    Parameters:
        ctx: The context instance (passed automatically).
    """
    from mypy.main import main as mypy

    class LazyStdout(StringIO):
        def __repr__(self) -> str:
            return "stdout"
        def write(self, value):
            return sys.stdout.write(value)

    class LazyStderr(StringIO):
        def __repr__(self) -> str:
            return "stderr"
        def write(self, value):
            return sys.stderr.write(value)

    os.environ["MYPY_FORCE_COLOR"] = "1"
    ctx.run(
        mypy,
        kwargs={
            "args": ["--config-file", "config/mypy.ini", *PY_SRC_LIST],
            "stdout": LazyStdout(),
            "stderr": LazyStderr(),
            "clean_exit": True,
        },
        title="Type-checking",
        command=f"mypy --config-file config/mypy.ini {PY_SRC}",
    )

It will require pawamoy/failprint#16, pawamoy/failprint#15, and pawamoy/failprint#14.

Feature: coverage badge

  • add a docs macro that outputs a JSON badge:

    @env.macro
    def get_coverage():
        data = json.load(Path("htmlcov/coverage.json").read_text())
        value = int(data["totals"]["percent_covered"])
        for threshold, hex in (
            (95, "#4c1"),  # brightgreen
            (90, "#97CA00"),  # green
            (75, "#a4a61d"),  # yellowgreen
            (60, "#dfb317"),  # yellow
            (40, "#fe7d37"),  # orange
            (0, "#e05d44"),  # red
        ):
            if value >= threshold:
                color = hex
                break
        return {"value": value, "color": color}
  • add a templated file coverage_badge.json to the docs:

    {% with get_coverage() as coverage %}
    {"schemaVersion": 1, "label": "coverage", "message": "{{ coverage.value }}", "color": "{{ coverage.color }}"}
    {% endwith %}
    
  • add a badge to the readme pointing to that published JSON file:

    [![coverage](https://img.shields.io/endpoint?url=https://namespace.github.io/project/coverage_badge.json)](https://namespace.github.io/project/coverage)

"make docs" triggers jinja2 error: more_credits is undefined

Hi there!

The error is triggered when executing make docs:

$ make docs
βœ— Building documentation (1)
  > mkdocs build
  INFO     -  Cleaning site directory
  INFO     -  Building documentation to directory: /Users/fperez/dev/llull/site
  Traceback (most recent call last):
    File "/Users/fperez/dev/llull/__pypackages__/3.7/bin/mkdocs", line 8, in <module>
      sys.exit(cli())
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/click/core.py", line 1128, in __call__
      return self.main(*args, **kwargs)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/click/core.py", line 1053, in main
      rv = self.invoke(ctx)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/click/core.py", line 1659, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/click/core.py", line 1395, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/click/core.py", line 754, in invoke
      return __callback(*args, **kwargs)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/mkdocs/__main__.py", line 187, in build_command
      build.build(config.load_config(**kwargs), dirty=not clean)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/mkdocs/commands/build.py", line 282, in build
      files = config['plugins'].run_event('files', files, config=config)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/mkdocs/plugins.py", line 102, in run_event
      result = method(item, **kwargs)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/mkdocs_gen_files/plugin.py", line 33, in on_files
      runpy.run_path(file_name)
    File "/Users/fperez/anaconda3/lib/python3.7/runpy.py", line 263, in run_path
      pkg_name=pkg_name, script_name=fname)
    File "/Users/fperez/anaconda3/lib/python3.7/runpy.py", line 96, in _run_module_code
      mod_name, mod_spec, pkg_name, script_name)
    File "/Users/fperez/anaconda3/lib/python3.7/runpy.py", line 85, in _run_code
      exec(code, run_globals)
    File "docs/gen_credits.py", line 62, in <module>
      fd.write(get_credits())
    File "docs/gen_credits.py", line 58, in get_credits
      return jinja_env.from_string(template_text).render(**template_data)
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/jinja2/environment.py", line 1291, in render
      self.environment.handle_exception()
    File "/Users/fperez/dev/llull/__pypackages__/3.7/lib/jinja2/environment.py", line 925, in handle_exception
      raise rewrite_traceback_stack(source=source)
    File "<template>", line 24, in top-level template code
  jinja2.exceptions.UndefinedError: 'more_credits' is undefined

make: *** [docs] Error 1

It is due to the fact that the variable more_docs is not defined by the jinja2 template if author_username is not "pawamoy". I will submit a PR to fix it.

What's the correct way to install test dependencies locally?

If I add a module such as requests to a project via pdm add, what is the proper way to ensure it gets added to all the versions of python when running make tests? I see in the GH workflow how it's being done, but not when developing locally.

Is this something pdm should do, pytest, or some other process?

Option to use venvs using environment variable

Love the plugin, just had an issue where my virtual environments were named after their python versions (e.g., 3.8.17, 3.9.17) and I found that I kept getting muddled between venvs and PEP 582 style environments because I'd forget to add the -e flag to my commands.

Suggesting a new feature where there is an environment variable, PDM_MULTIRUN_USE_VENVS which when set to 1 will use virtual environments by default.

Thanks (again) for another great tool!

The template arrangement is super well executed - so transition from a productive project based on copier.poetry was really really smooth [1].

And: Yes, pdm rocks...
This has to be the future of python packaging - so glad you invested the work in supporting it, so well aligned with copier.poetry.

Cheers & Thanks again!!,
G.

PS: Again, a little problem to justify the issue here:
Took me quite a while (had not all brains available) to find out that optional dev.dependencies are not yet supported in current pipx installed pdm version. Imho that would be worth a note or a comment in the generated pyproject.toml file, to not frustrate others when first trying copier.pdm. Not sure when this is supported.

feat: Consider creating a copier-hatch template

After thinking about it, I don't really have a use-case for dependency locking. I only use the lock file to install dependencies under multiple Python versions. I don't track it, I don't have reproducible builds in CI (tradeoff for other maintenance benefits). So I could definitely switch to something lighter like Hatch, which simply installs dependencies using pip IIUC. Hatch also provides environments isolation, which is very interesting to me. My dev-deps pollute the version resolution of my prod-deps, while most of the time, my dev-deps work statically, so do not require having the prod-deps installed (pytest is the exception).

So, todo:

  • try Hatch in an existing project, see if the migration is smooth (articles? guides?)
  • see how Hatch environments fit my workflow, if their verbosity in pyproject.toml is maintainable
  • see if Hatch's output is configurable: I want to retain my very minimalist output, it's non-negociable πŸ™‚
  • see the perfs: installing deps, updating deps, running check/test commands
  • see if Hatch's recent ability to install compiled Python versions fits my workflow

problems w/ new project

There are a few problems creating a new project from scratch:

  1. If there is no python 3.7, I get errors like this:
make check-types
[NoPythonVersion]: No Python interpreter matching python3.7 is found.
make: *** [Makefile:52: check-types] Error 1
  1. the template should prompt for the range of python versions we want

After the project was created, I updated pyproject.toml like this:

requires-python = ">=3.8,<3.12"
keywords = []
dynamic = ["version"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Topic :: Documentation",
    "Topic :: Software Development",
    "Topic :: Utilities",
    "Typing :: Typed",
]
  1. After this, I get errors like this:
make check
[NoPythonVersion]: No python is found meeting the requirement python >=3.8,<3.12
make: *** [Makefile:43: check] Error 1

Where is this version check coming from?

  1. Looking at pdm-multirun, I wonder whether the Makefile should set PDM_MULTIRUN_VERSIONS

I tried it manually:

pdm multirun -i 3.11 duty check-types
Traceback (most recent call last):
  File "/home/nfr/.local/bin/duty", line 5, in <module>
    from duty.cli import main
ModuleNotFoundError: No module named 'duty'

This is surprising because I see in pyproject.toml the following:

[tool.pdm.dev-dependencies]
duty = ["duty>=0.10"]

Any suggestions on addressing these problems?

feat: Direnv + Devbox support

In .envrc:

# Automatically sets up your devbox environment whenever you cd into this
# directory via our direnv integration:

eval "$(
    devbox generate direnv --print-envrc ||
    echo echo Install Devbox: https://www.jetpack.io/devbox/docs/installing_devbox/#install-devbox
)"

# check out https://www.jetpack.io/devbox/docs/ide_configuration/direnv/
# for more details

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.