Skip to content

Commit

Permalink
ci => actions
Browse files Browse the repository at this point in the history
packageize
  • Loading branch information
scivision committed Dec 9, 2019
1 parent 53c5407 commit 1d44ddc
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 96 deletions.
4 changes: 3 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[flake8]
max-line-length = 132
exclude = .git,__pycache__,.eggs/,doc/,docs/,build/,dist/,archive/
exclude = .git,__pycache__,.eggs/,doc/,docs/,build/,dist/,archive/
per-file-ignores =
__init__.py:F401
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: [scivision]
ko_fi: scivision
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: ci

on:
push:
paths:
- "**.py"
- ".github/workflows/ci.yml"
pull_request:
paths:
- "**.py"
- ".github/workflows/ci.yml"

jobs:

linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: pip install .[tests,lint]
- run: flake8
- run: mypy .
- run: pytest
working-directory: tests

integration:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macos-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: pip install .[tests]
- run: pytest
working-directory: tests
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
[![DOI](https://zenodo.org/badge/186922933.svg)](https://zenodo.org/badge/latestdoi/186922933)

[![Build Status](https://travis-ci.com/scivision/meldutils.svg?branch=master)](https://travis-ci.com/scivision/meldutils)
[![Coverage Status](https://coveralls.io/repos/github/scivision/meldutils/badge.svg?branch=master)](https://coveralls.io/github/scivision/meldutils?branch=master)
[![Build status](https://ci.appveyor.com/api/projects/status/l2qshn68va0by813?svg=true)](https://ci.appveyor.com/project/scivision/meldutils)

# Meld Utilities

Python scripts using [Meld](https://meldmerge.org) to accomplish tasks useful for managing large numbers of repos / projects, particularly for templates.
It works on any OS Meld works on (Linux, MacOS, Windows).
[![DOI](https://zenodo.org/badge/186922933.svg)](https://zenodo.org/badge/latestdoi/186922933)
[![Actions Status](https://github.com/scivision/meldutils/workflows/ci/badge.svg)](https://github.com/scivision/meldutils/actions)

Python scripts using
[Meld](https://meldmerge.org)
to accomplish tasks useful for managing large numbers of repos / projects, particularly for templates.
It works on any OS Meld works on (Linux, MacOS, Windows).

## Scripts

Expand All @@ -18,7 +16,6 @@ meld_all project/myfile.f90 ~/code

That terminal command invokes `meld` between `project/myfile.f90` and every other file with the same name found recursively under `~/code`.


### Usage

Particularly on Windows, you may get Meld brought up and you don't see any difference.
Expand Down
File renamed without changes.
File renamed without changes.
84 changes: 14 additions & 70 deletions meld_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,94 +10,38 @@
"""
from pathlib import Path
from argparse import ArgumentParser
from typing import Iterator
import filecmp
import meldutils as mu
import logging
import subprocess
import shutil
try:
import ghlinguist as ghl
except (ImportError, FileNotFoundError):
ghl = None


def files_to_meld(root: Path, ref: Path,
language: str = None,
strict: bool = False) -> Iterator[Path]:

si = 1 if strict else 2

ref = Path(ref).expanduser()
if not ref.is_file():
raise FileNotFoundError(f'specify a reference file, not a directory {ref}')

root = Path(root).expanduser()
if not root.is_dir():
raise NotADirectoryError(root)

for new in root.rglob(ref.name):
if new.samefile(ref):
continue

if filecmp.cmp(new, ref, shallow=False): # type: ignore # mypy .pyi needs updating
logging.info(f'SAME: {new.parent}')
continue

if language and ghl is not None:
langlist = ghl.linguist(new.parent)
if langlist is None:
logging.info(f'SKIP: {new.parent}')
continue

thislangs = [l[0] for l in langlist[:si]]
if language not in thislangs:
logging.info(f'SKIP: {new.parent} {thislangs}')
continue

yield new


def meld_files(ref: Path, new: Path, rexe: str):
"""
run file comparison program (often meld) on file pair
"""

exe = shutil.which(rexe)
if not exe:
logging.critical('File comparison program not found. Try -n option to just see which files differ.')
raise FileNotFoundError(rexe)
# Not using check_call due to spurious errors
new = Path(new).expanduser()
ref = Path(ref).expanduser()
subprocess.run([exe, str(ref), str(new)])


def main():
p = ArgumentParser()
p.add_argument('ref', help='filename to compare against')
p.add_argument('root', help='top-level directory to search under')
p.add_argument('-l', '--language', help='language to template')
p.add_argument('-exe', help='program to compare with', default='meld')
p.add_argument('-s', '--strict', help='compare only with first language match', action='store_true')
p.add_argument('-n', '--dryrun', help='just report files that are different', action='store_true')
p.add_argument("ref", help="filename to compare against")
p.add_argument("root", help="top-level directory to search under")
p.add_argument("-l", "--language", help="language to template")
p.add_argument("-exe", help="program to compare with", default="meld")
p.add_argument("-s", "--strict", help="compare only with first language match", action="store_true")
p.add_argument("-n", "--dryrun", help="just report files that are different", action="store_true")
p = p.parse_args()

if p.dryrun:
level = logging.INFO
else:
level = logging.WARNING
logging.basicConfig(format='%(message)s', level=level)
logging.basicConfig(format="%(message)s", level=level)

root = Path(p.root).expanduser()
if not root.is_dir():
raise SystemExit(f"{root} is not a directory")

files = files_to_meld(root, p.ref, p.language, strict=p.strict)
files = mu.files_to_meld(root, p.ref, p.language, strict=p.strict)

for file in files:
if p.dryrun:
print(f'{file} != {p.ref}')
print(f"{file} != {p.ref}")
else:
meld_files(p.ref, file, p.exe)
mu.meld_files(p.ref, file, p.exe)


if __name__ == '__main__':
if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions meldutils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .base import files_to_meld, meld_files
59 changes: 59 additions & 0 deletions meldutils/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import typing
from pathlib import Path
import shutil
import subprocess
import logging
import filecmp

try:
import ghlinguist as ghl
except (ImportError, FileNotFoundError):
ghl = None


def files_to_meld(root: Path, ref: Path, language: str = None, strict: bool = False) -> typing.Iterator[Path]:

si = 1 if strict else 2

ref = Path(ref).expanduser()
if not ref.is_file():
raise FileNotFoundError(f"specify a reference file, not a directory {ref}")

root = Path(root).expanduser()
if not root.is_dir():
raise NotADirectoryError(f"{root} is not a directory")

for new in root.rglob(ref.name):
if new.samefile(ref):
continue

if filecmp.cmp(new, ref, shallow=False): # type: ignore # mypy .pyi needs updating
logging.info(f"SAME: {new.parent}")
continue

if language and ghl is not None:
langlist = ghl.linguist(new.parent)
if langlist is None:
logging.info(f"SKIP: {new.parent}")
continue

thislangs = [l[0] for l in langlist[:si]]
if language not in thislangs:
logging.info(f"SKIP: {new.parent} {thislangs}")
continue

yield new


def meld_files(ref: Path, new: Path, rexe: str):
"""
run file comparison program (often meld) on file pair
"""

exe = shutil.which(rexe)
if not exe:
raise FileNotFoundError(f"{rexe} not found. Try -n option to just see which files differ.")
# Not using check_call due to spurious errors
new = Path(new).expanduser()
ref = Path(ref).expanduser()
subprocess.run([exe, str(ref), str(new)])
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[build-system]
requires = ["setuptools", "wheel"]
requires = ["setuptools", "wheel"]

[tool.black]
line-length = 132
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
addopts = -ra -v
8 changes: 4 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = meldutils
version = 1.0.2
version = 1.1.0
author = Michael Hirsch, Ph.D.
author_email = scivision@users.noreply.github.com
description = Python utilities for Meld, good for managing templates across lots of repos / projects
Expand All @@ -18,6 +18,8 @@ classifiers =
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Topic :: Software Development :: Version Control
Topic :: Utilities
license_files =
LICENSE.txt
Expand All @@ -34,9 +36,7 @@ install_requires =
[options.extras_require]
tests =
pytest
cov =
pytest-cov
coveralls
lint =
flake8
mypy
linguist =
Expand Down
22 changes: 11 additions & 11 deletions test_meld.py → tests/test_meld.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
from pathlib import Path
import os

import meld_all as mu
import meldutils as mu


@pytest.fixture
def gen_file(tmp_path):
f1 = tmp_path/'a/hi.txt'
f2 = tmp_path/'b/hi.txt'
f1 = tmp_path / "a/hi.txt"
f2 = tmp_path / "b/hi.txt"

make_file(f1)
make_file(f2)
Expand All @@ -19,7 +19,7 @@ def gen_file(tmp_path):

def make_file(path: Path):
path.parent.mkdir(exist_ok=True, parents=True)
path.write_text('hello')
path.write_text("hello")


def test_find(gen_file):
Expand All @@ -30,8 +30,8 @@ def test_find(gen_file):
assert len(files) == 0

# add a whitespace to one file to make the file slightly different than the other file
with f2.open('a') as f:
f.write(' ')
with f2.open("a") as f:
f.write(" ")

files = list(mu.files_to_meld(f1.parents[1], f1))

Expand All @@ -40,15 +40,15 @@ def test_find(gen_file):

def test_diff(gen_file):
f1, f2 = gen_file
f2.write_text('hi')
f2.write_text("hi")

if os.name == 'nt':
diff = 'FC'
if os.name == "nt":
diff = "FC"
else:
diff = 'diff'
diff = "diff"

mu.meld_files(f1.parents[1], f1, diff)


if __name__ == '__main__':
if __name__ == "__main__":
pytest.main([__file__])

0 comments on commit 1d44ddc

Please sign in to comment.