Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor prettier invocation #1974

Merged
merged 6 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 25 additions & 51 deletions nf_core/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
import imghdr
import logging
import os
import pathlib
import random
import re
import shutil
import subprocess
import sys
import time
from pathlib import Path

import git
import jinja2
Expand All @@ -23,6 +22,7 @@
import nf_core
import nf_core.schema
import nf_core.utils
from nf_core.lint_utils import run_prettier_on_file

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -89,7 +89,7 @@ def __init__(
self.force = force
if outdir is None:
outdir = os.path.join(os.getcwd(), self.template_params["name_noslash"])
self.outdir = outdir
self.outdir = Path(outdir)

def create_param_dict(self, name, description, author, version, template_yaml_path, plain):
"""Creates a dictionary of parameters for the new pipeline.
Expand Down Expand Up @@ -236,17 +236,18 @@ def init_pipeline(self):
if self.template_params["branded"]:
log.info(
"[green bold]!!!!!! IMPORTANT !!!!!!\n\n"
+ "[green not bold]If you are interested in adding your pipeline to the nf-core community,\n"
+ "PLEASE COME AND TALK TO US IN THE NF-CORE SLACK BEFORE WRITING ANY CODE!\n\n"
+ "[default]Please read: [link=https://nf-co.re/developers/adding_pipelines#join-the-community]https://nf-co.re/developers/adding_pipelines#join-the-community[/link]"
"[green not bold]If you are interested in adding your pipeline to the nf-core community,\n"
"PLEASE COME AND TALK TO US IN THE NF-CORE SLACK BEFORE WRITING ANY CODE!\n\n"
"[default]Please read: [link=https://nf-co.re/developers/adding_pipelines#join-the-community]"
"https://nf-co.re/developers/adding_pipelines#join-the-community[/link]"
)

def render_template(self):
"""Runs Jinja to create a new nf-core pipeline."""
log.info(f"Creating new nf-core pipeline: '{self.name}'")

# Check if the output directory exists
if os.path.exists(self.outdir):
if self.outdir.exists():
if self.force:
log.warning(f"Output directory '{self.outdir}' exists - continuing as --force specified")
else:
Expand All @@ -265,12 +266,13 @@ def render_template(self):
object_attrs["nf_core_version"] = nf_core.__version__

# Can't use glob.glob() as need recursive hidden dotfiles - https://stackoverflow.com/a/58126417/713980
template_files = list(pathlib.Path(template_dir).glob("**/*"))
template_files += list(pathlib.Path(template_dir).glob("*"))
template_files = list(Path(template_dir).glob("**/*"))
template_files += list(Path(template_dir).glob("*"))
ignore_strs = [".pyc", "__pycache__", ".pyo", ".pyd", ".DS_Store", ".egg"]
short_name = self.template_params["short_name"]
rename_files = {
"workflows/pipeline.nf": f"workflows/{self.template_params['short_name']}.nf",
"lib/WorkflowPipeline.groovy": f"lib/Workflow{self.template_params['short_name'][0].upper()}{self.template_params['short_name'][1:]}.groovy",
"workflows/pipeline.nf": f"workflows/{short_name}.nf",
"lib/WorkflowPipeline.groovy": f"lib/Workflow{short_name[0].upper()}{short_name[1:]}.groovy",
}

# Set the paths to skip according to customization
Expand All @@ -291,9 +293,9 @@ def render_template(self):

# Set up vars and directories
template_fn = os.path.relpath(template_fn_path, template_dir)
output_path = os.path.join(self.outdir, template_fn)
output_path = self.outdir / template_fn
if template_fn in rename_files:
output_path = os.path.join(self.outdir, rename_files[template_fn])
output_path = self.outdir / rename_files[template_fn]
os.makedirs(os.path.dirname(output_path), exist_ok=True)

try:
Expand Down Expand Up @@ -345,7 +347,7 @@ def update_nextflow_schema(self):
"""
Removes unused parameters from the nextflow schema.
"""
schema_path = os.path.join(self.outdir, "nextflow_schema.json")
schema_path = self.outdir / "nextflow_schema.json"

schema = nf_core.schema.PipelineSchema()
schema.schema_filename = schema_path
Expand All @@ -354,22 +356,14 @@ def update_nextflow_schema(self):
schema.get_wf_params()
schema.remove_schema_notfound_configs()
schema.save_schema(suppress_logging=True)

# The schema is not guaranteed to follow Prettier standards
# so we run prettier on the schema file
try:
subprocess.run(
["prettier", "--write", schema_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False
)
except FileNotFoundError:
log.warning("Prettier not found. Please install it and run it on the pipeline to fix linting issues.")
run_prettier_on_file(schema_path)

def remove_nf_core_in_bug_report_template(self):
"""
Remove the field mentioning nf-core documentation
in the github bug report template
"""
bug_report_path = os.path.join(self.outdir, ".github", "ISSUE_TEMPLATE", "bug_report.yml")
bug_report_path = self.outdir / ".github" / "ISSUE_TEMPLATE" / "bug_report.yml"

with open(bug_report_path, "r") as fh:
contents = yaml.load(fh, Loader=yaml.FullLoader)
Expand All @@ -380,17 +374,7 @@ def remove_nf_core_in_bug_report_template(self):
with open(bug_report_path, "w") as fh:
yaml.dump(contents, fh, default_flow_style=False, sort_keys=False)

# The dumped yaml file will not follow prettier formatting rules
# so we run prettier on the file
try:
subprocess.run(
["prettier", "--write", bug_report_path],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
)
except FileNotFoundError:
log.warning("Prettier not found. Please install it and run it on the pipeline to fix linting issues.")
run_prettier_on_file(bug_report_path)

def fix_linting(self):
"""
Expand Down Expand Up @@ -455,34 +439,24 @@ def fix_linting(self):
# Add the lint content to the preexisting nf-core config
nf_core_yml = nf_core.utils.load_tools_config(self.outdir)
nf_core_yml["lint"] = lint_config
with open(os.path.join(self.outdir, ".nf-core.yml"), "w") as fh:
with open(self.outdir / ".nf-core.yml", "w") as fh:
yaml.dump(nf_core_yml, fh, default_flow_style=False, sort_keys=False)

# The dumped yaml file will not follow prettier formatting rules
# so we run prettier on the file
try:
subprocess.run(
["prettier", "--write", os.path.join(self.outdir, ".nf-core.yml")],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
)
except FileNotFoundError:
log.warning(
"Prettier is not installed. Please install it and run it on the pipeline to fix linting issues."
)
run_prettier_on_file(os.path.join(self.outdir, ".nf-core.yml"))

def make_pipeline_logo(self):
"""Fetch a logo for the new pipeline from the nf-core website"""

logo_url = f"https://nf-co.re/logo/{self.template_params['short_name']}?theme=light"
log.debug(f"Fetching logo from {logo_url}")

email_logo_path = f"{self.outdir}/assets/{self.template_params['name_noslash']}_logo_light.png"
email_logo_path = self.outdir / "assets" / f"{self.template_params['name_noslash']}_logo_light.png"
self.download_pipeline_logo(f"{logo_url}&w=400", email_logo_path)
for theme in ["dark", "light"]:
readme_logo_url = f"{logo_url}?w=600&theme={theme}"
readme_logo_path = f"{self.outdir}/docs/images/{self.template_params['name_noslash']}_logo_{theme}.png"
readme_logo_path = (
fabianegli marked this conversation as resolved.
Show resolved Hide resolved
self.outdir / "docs" / "images" / f"{self.template_params['name_noslash']}_logo_{theme}.png"
)
self.download_pipeline_logo(readme_logo_url, readme_logo_path)

def download_pipeline_logo(self, url, img_fn):
Expand Down
22 changes: 22 additions & 0 deletions nf_core/lint_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import subprocess

import rich
from rich.console import Console
Expand Down Expand Up @@ -47,3 +48,24 @@ def print_fixes(lint_obj, module_lint_obj):
console.print(
"Automatic fixes applied. Please check with 'git diff' and revert any changes you do not want with 'git checkout <file>'."
)


def run_prettier_on_file(file):
"""Runs Prettier on a file if Prettier is installed.

Args:
file (Path | str): A file identifier as a string or pathlib.Path.

Warns:
If Prettier is not installed, a warning is logged.
"""

try:
subprocess.run(
["prettier", "--write", file],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
)
except FileNotFoundError:
log.warning("Prettier is not installed. Please install it and run it on the pipeline to fix linting issues.")
fabianegli marked this conversation as resolved.
Show resolved Hide resolved