Skip to content

Commit

Permalink
Moving to github actions.
Browse files Browse the repository at this point in the history
  • Loading branch information
thebjorn committed Nov 30, 2023
1 parent 7818254 commit 5fde4df
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 83 deletions.
135 changes: 135 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: CI/CD Pipeline

on: [ push, pull_request, workflow_dispatch ]

env:
PIP_CACHE_DIR: /tmp/pipcache
HOME_REPO: datakortet/dkfileutils

jobs:
ci-lint:
name: CI:Lint
runs-on: ubuntu-latest
env:
LINTDIR: ./ghlint
steps:
# setup environment
- uses: actions/checkout@v3
- name: setup directories
shell: bash
run: |
mkdir -p $PIP_CACHE_DIR
mkdir -p $LINTDIR
- uses: actions/setup-python@v4
with:
python-version: '3.9'

- run: pip install flake8
- run: flake8 dkfileutils/** --max-line-length=199

docs:
name: CI:Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: setup directories
shell: bash
run: |
mkdir -p build
- run: pip install sphinx
- run: pip install -e .
- run: sphinx-build -W -b html docs build/sphinx/html
- run: sphinx-build -W -n -T -b man docs build/sphinx/man

- name: Upload docs as artifact
uses: actions/upload-artifact@v3
with:
name: Docs
path: build/sphinx/

ci-test:
name: CI:Test
runs-on: ${{ matrix.os }}
strategy:
matrix:

python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12']

os: [ubuntu-latest]
include:
- python-version: '3.12'
os: windows-latest
- python-version: '3.12'
os: macos-latest

steps:
# setup environment
- uses: actions/checkout@v3
- name: setup global directories
shell: bash
run: mkdir -p $PIP_CACHE_DIR
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- run: pip install -r requirements.txt
- run: pip list
- run: pytest -vv --cov=dkfileutils tests

- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN}}
fail_ci_if_error: false

cd:
name: CD
needs: ci-test
runs-on: ubuntu-latest
steps:
# setup environment
- uses: actions/checkout@v3
- name: setup directories
shell: bash
run: mkdir -p $PIP_CACHE_DIR
- uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Cleanup
run: |
rm -rf dist
rm -rf build
- run: pip install -U build twine
- run: python -m build

- name: Upload packages as artifact
uses: actions/upload-artifact@v3
with:
name: Packages
path: dist/

- name: Deploy to PyPI
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.repository == env.HOME_REPO
shell: bash
run: |
twine upload -u __token__ -p ${{ secrets.PYPI_API_TOKEN }} dist/*
# - name: Publish package
# uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
# with:
# user: __token__
# password: ${{ secrets.PYPI_API_TOKEN }}

- name: Create Github release
uses: ncipollo/release-action@v1
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.repository == env.HOME_REPO
with:
artifacts: "dist/*"
owner: datakortet
repo: dkfileutils
token: ${{ secrets.GITHUB_TOKEN }}
13 changes: 13 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 2

build:
os: ubuntu-22.04
tools:
python: "3.11"

sphinx:
configuration: docs/conf.py

python:
install:
- requirements: requirements.txt
21 changes: 0 additions & 21 deletions .travis.yml

This file was deleted.

36 changes: 7 additions & 29 deletions DEVELOP.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,16 @@
Developing dkfileutils
======================

.. note:: if you're using this as a template for new projects, remember to
``python setup.py register <projectname>`` before you upload to
PyPi.

Uploading to PyPI
-----------------
This requires pyinvoke (``pip install invoke``) and dk-tasklib
(``pip install dk-tasklib``). These are not listed as requirements.
New versions are automatically uploaded to PyPI when a new tag is pushed to
GitHub. To create a new tag, run::

Create a new version::
git tag -a v0.1.0 -m "Version 0.1.0"
git push --tags

inv upversion

Build everything::

inv -e build -f

Check in new version numbers:

git add ...
git commit ...

Verify that everything is copacetic::

inv publish

Tag the release (replace 1.2.3 with the new version number)::

git tag -a v1.2.3 -m "Version 1.2.3"
git push origin --tags

then push to PyPi::

inv publish -f
(or internally ``dk upversion --tag``)


Running tests
Expand All @@ -59,3 +35,5 @@ Building documentation

python setup.py build_sphinx

internally (``dk docs``).

12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
dkfileutils - file and directory utilities
==========================================

.. image:: https://travis-ci.org/datakortet/dkfileutils.svg?branch=master
:target: https://travis-ci.org/datakortet/dkfileutils

.. image:: https://coveralls.io/repos/datakortet/dkfileutils/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/datakortet/dkfileutils?branch=master

.. image:: https://readthedocs.org/projects/dkfileutils/badge/?version=latest

.. image:: https://codecov.io/gh/datakortet/dkfileutils/branch/master/graph/badge.svg
Expand Down Expand Up @@ -41,6 +35,12 @@ friends. Similar to the Python 3 `pathlib`, however paths are
`str` subclasses and thus much easier to use in an environment
where `os.path` calls are interspersed with object-oriented code.

Brett Cannon strongly dislikes paths being `str` subclasses, see
https://snarky.ca/why-pathlib-path-doesn-t-inherit-from-str/
While I can agree with him in principle, this is clearly a case
of "practicality beats purity". The official ``pathlib`` version
of ``'/b/' in Path('/a/b/c')`` is rather baroque.

pfind
~~~~~
Find directory where a file is located by walking up parent directories.
Expand Down
14 changes: 6 additions & 8 deletions dkfileutils/changed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
"""Check if contents of directory has changed.
"""
from __future__ import print_function
import argparse
import os
import hashlib
Expand All @@ -25,12 +23,12 @@ def digest(dirname, glob=None):
return md5.hexdigest()


def changed(dirname, filename='.md5', args=None, glob=None):
def changed(dirname, filename='.md5', args=None, glob=None) -> bool:
"""Has `glob` changed in `dirname`
Args:
dirname: directory to measure
filename: filename to store checksum
Args:
dirname: directory to measure
filename: filename to store checksum
"""
root = Path(dirname)
if not root.exists():
Expand All @@ -39,7 +37,7 @@ def changed(dirname, filename='.md5', args=None, glob=None):

cachefile = root / filename
current_digest = cachefile.open().read() if cachefile.exists() else ""

_digest = digest(dirname, glob=glob)
if args and args.verbose: # pragma: nocover
print("md5:", _digest)
Expand All @@ -55,7 +53,7 @@ def changed(dirname, filename='.md5', args=None, glob=None):
class Directory(Path):
"""A path that is a directory.
"""
def changed(self, filename='.md5', glob=None):
def changed(self, filename='.md5', glob=None) -> bool:
"""Are any of the files matched by ``glob`` changed?
"""
if glob is not None:
Expand Down
27 changes: 11 additions & 16 deletions dkfileutils/path.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
# -*- coding: utf-8 -*-
"""Poor man's pathlib.
"""
Poor man's pathlib.
(Path instances are subclasses of str, so interoperability with existing
os.path code is greater than with Python 3's pathlib.)
(Path instances are subclasses of str, so interoperability with existing
os.path code is greater than with Python 3's pathlib.)
"""
# pylint:disable=C0111,R0904
# R0904: too many public methods in Path
from __future__ import print_function
from __future__ import annotations
import os
import re
from contextlib import contextmanager
import shutil

from typing import BinaryIO, Text, Union
from typing import BinaryIO, Text


def doc(srcfn):
Expand All @@ -35,7 +33,7 @@ def __new__(cls, *args, **kw):
else:
return str.__new__(cls, os.path.normcase(args[0]), **kw)

def __div__(self, other: str) -> 'Path': # type: (Union[Path, Text]) -> Path
def __div__(self, other: Path | str) -> 'Path':
return Path(
os.path.normcase(
os.path.normpath(
Expand Down Expand Up @@ -101,9 +99,9 @@ def curdir(cls):
def touch(self, mode=0o666, exist_ok=True):
"""Create this file with the given access mode, if it doesn't exist.
Based on:
https://github.com/python/cpython/blob/master/Lib/pathlib.py)
"""
if exist_ok:
# First try to bump modification time
Expand All @@ -122,7 +120,7 @@ def touch(self, mode=0o666, exist_ok=True):
fd = os.open(self, flags, mode)
os.close(fd)

def glob(self, pat):
def glob(self, pat: str) -> list[Path]:
"""`pat` can be an extended glob pattern, e.g. `'**/*.less'`
This code handles negations similarly to node.js' minimatch, i.e.
a leading `!` will negate the entire pattern.
Expand All @@ -148,9 +146,6 @@ def glob(self, pat):
r += pat[i]
i += 1
r += r'\Z(?ms)'
# print '\n\npat', pat
# print 'regex:', r
# print [s.relpath(self).replace('\\', '/') for s in self]
rx = re.compile(r)

def match(d):
Expand Down Expand Up @@ -393,7 +388,7 @@ def removedirs(self):
@doc(shutil.move)
def move(self, dst):
return shutil.move(self, dst)

@doc(shutil.copy)
def copy(self, dst):
return shutil.copy(self, dst)
Expand Down
6 changes: 3 additions & 3 deletions dkfileutils/which.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ def which(filename, interactive=False, verbose=False):
raise ValueError("which can only search for executable files")

def match(filenames):
"""Returns the sorted subset of ``filenames`` that matches
"""Returns the sorted subset of ``filenames`` that matches
``filename``.
"""
res = set()
for fname in filenames:
if fname == filename: # pragma: nocover
res.add(fname) # exact match
continue
fname_name, fname_ext = os.path.splitext(fname)
if fname_name == name and fname_ext.lower() in exe: # pragma: nocover
fname_name, ext = os.path.splitext(fname)
if fname_name == name and ext.lower() in exe: # pragma: nocover
res.add(fname)
return sorted(res)

Expand Down

0 comments on commit 5fde4df

Please sign in to comment.