diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ec8cf5093de54a4cc555ae59fdb342932394a8a8..75f0ec3781ad144d94bafd3ed68ad027b9bcf0be 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,6 @@ test_python39: image: python:3.9 - test_python310: extends: .test image: python:3.10 @@ -52,6 +51,9 @@ test_python311: extends: .test image: python:3.11 +test_python312: + extends: .test + image: python:3.12 .build_python: only: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e787f6718bd182ee659b6469153b35ebe2fcdee..19a1465b81a77cd1b39cbbf847b4204f13a50dfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * got rid of the Mako dependency * should work on latest Pythons * moved the development to SMOK's cloud +* got rid of Satella dependency # v1.7 diff --git a/README.md b/README.md index d04c92ff05af4294b082e6b16eef738eabfbee62..aefa23cf2c51ed2fb04c9ce25a4269b020b87e0b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Since for now we've lost our PyPI access, please install the packages in a follo pip install git+https://github.com/smok-serwis/snakehouse.git ``` +The software works all the way from Python 3.5 to Python 3.12. + snakehouse is a tool to pack mutiple .pyx files into a single extension so that they are importable as separate Python modules inside Python. diff --git a/setup.cfg b/setup.cfg index 8b7cea7daa005bc4aa4f515deb32c8fd429b34ea..e295927cf348e94491c55e658cb827b878cdac04 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,6 @@ classifier = [options] install_requires = Cython - satella python_requires = !=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.* packages = snakehouse diff --git a/snakehouse/multibuild.py b/snakehouse/multibuild.py index 424c20c1cddb25d9ad60b44870adc6518a7b2685..cdd8e83d0b34841cd16089c2ae6f12a031b0abbb 100644 --- a/snakehouse/multibuild.py +++ b/snakehouse/multibuild.py @@ -7,7 +7,7 @@ import typing as tp import warnings import pkg_resources -from satella.files import split, find_files +from .satella import split, find_files from setuptools import Extension from .templating import HFILE_MAKO, INITPY_MAKO from. bootstrap import get_file diff --git a/snakehouse/requirements.py b/snakehouse/requirements.py index 1e8fbe03d5ec48a6ec0f1b4796a5c24c5591afc3..4fce3ee9ae33f7b9a0cd17cd7affc0de62c4e859 100644 --- a/snakehouse/requirements.py +++ b/snakehouse/requirements.py @@ -1,7 +1,6 @@ import typing as tp import warnings -from satella.coding import for_argument from satella.files import read_lines, find_files @@ -60,3 +59,21 @@ def read_requirements_txt(path: str = 'requirements.txt'): lines = (line for line in lines if not line.startswith('http')) lines = (line for line in lines if line) return list(lines) + +def read_lines(path: str, delete_empty_lines: bool = True, + encoding: str = 'utf-8') -> tp.List[str]: + """ + Read lines from a particular file, removing end-of-line characters and optionally + empty lines. Additionally whitespaces (and end-of-line characters) will be removed + from both ends of each line. + + :param path: path of file to read + :param delete_empty_lines: set to False if empty lines are not to be removed + :param encoding: encoding to read the file with + :return: each line as a separate entry + """ + with codecs.open(path, 'r', encoding) as f_in: + lines = [line.strip() for line in f_in.readlines()] + if delete_empty_lines: + lines = [line for line in lines if line] + return lines \ No newline at end of file diff --git a/snakehouse/satella.py b/snakehouse/satella.py new file mode 100644 index 0000000000000000000000000000000000000000..30867bfed642c4c3eda95ece27bce0af1c5109ac --- /dev/null +++ b/snakehouse/satella.py @@ -0,0 +1,57 @@ +def find_files(path: str, wildcard: str = r'(.*)', + prefix_with: tp.Optional[str] = None, + scan_subdirectories: bool = True, + apply_wildcard_to_entire_path: bool = False, + prefix_with_path: bool = True) -> tp.Iterator[str]: + """ + Look at given path's files and all subdirectories and return an iterator of + file names (paths included) that conform to given wildcard. + + Note that wildcard is only applied to the file name if apply_wildcard_to_entire_path + is False, else the wildcard is applied to entire path (including the application of + prefix_with!). + + Files will be additionally prefixed with path, but only if prefix_with_path is True + + .. warning:: Note that this will try to match only the start of the path. For a complete match + remember to put a $ at the end of the string! + + :param path: path to look into. + :param wildcard: a regular expression to match + :param prefix_with: an optional path component to prefix before the filename with os.path.join + :param scan_subdirectories: whether to scan subdirectories + :param apply_wildcard_to_entire_path: whether to take the entire relative path into account + when checking wildcard + :param prefix_with_path: whether to add path to the resulting path + :return: paths with the files. They will be relative paths, relative to path + """ + if prefix_with_path: + prefix_with = _cond_join(prefix_with, path) + + for filename in os.listdir(path): + if scan_subdirectories and os.path.isdir(os.path.join(path, filename)): + new_prefix = _cond_join(prefix_with, filename) + yield from find_files(os.path.join(path, filename), wildcard, + prefix_with=new_prefix, + prefix_with_path=False) + else: + if apply_wildcard_to_entire_path: + fn_path = _cond_join(prefix_with, filename) + else: + fn_path = filename + if re.match(wildcard, fn_path): + yield _cond_join(prefix_with, filename) + + +def split(path: str) -> tp.List[str]: + """ + An exact reverse of os.path.join + + Is is true that + + >>> os.path.join(split(a)) == a + """ + data = list(os.path.split(path)) + while _has_separator(data[0]): + data = list(os.path.split(data[0])) + data[1:] + return data \ No newline at end of file