diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..8cc7798 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [avanov] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2503d65 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: "CI" +on: + push: + branches: [ master, develop ] + pull_request: + branches: [ master, develop ] + +jobs: + tests: + strategy: + matrix: + python-version: [ 39, 310 ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2.3.4 + with: + submodules: recursive + - uses: cachix/install-nix-action@v12 + with: + install_url: https://releases.nixos.org/nix/nix-2.11.1/install + extra_nix_config: "system-features = benchmark kvm" + - name: Run tests on Python${{ matrix.python-version }} + run: | + nix-shell --argstr pyVersion ${{ matrix.python-version }} --run \ + "pip install -e . && pip install -r requirements.txt && pip install -r requirements-test.txt && python -m pytest" + + - name: Coveralls + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + nix-shell --argstr pyVersion ${{ matrix.python-version }} --run "coveralls --service=github" + + coveralls: + name: Coveralls [finalize] + needs: tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2.3.4 + with: + submodules: recursive + - uses: cachix/install-nix-action@v12 + with: + install_url: https://releases.nixos.org/nix/nix-2.11.1/install + extra_nix_config: "system-features = benchmark kvm" + - name: Coveralls [finalize] + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + nix-shell --run "coveralls --service=github --finish" diff --git a/.gitignore b/.gitignore index 6684a00..4acec87 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,11 @@ build/ dist/ *.egg-info/ +*.eggs/ +*.local/ +__pycache__/ +# npm package lock, we don't need it as the 'stylus' dependency is optional +package-lock.json docs/_build diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e413b83..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -language: python -before_install: - - npm install stylus@0.27.2 - - python setup.py develop -install: - - pip install coveralls -python: - - "2.7" - - "3.5" - -# command to run tests -script: python setup.py nosetests - -after_success: coveralls diff --git a/CHANGES b/CHANGES index 729b08f..93f4541 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,13 @@ Changelog ================ +1.0.0 +----- + +- Dropped support for Python 2.x +- Test suite switched from Nose to Pytest +- CI switched from Travis CI to Github Actions + Version 0.9 ------------- diff --git a/README.rst b/README.rst index f770960..82314ef 100644 --- a/README.rst +++ b/README.rst @@ -1,20 +1,21 @@ Plim ============== -.. image:: https://pypip.in/v/Plim/badge.png +.. image:: https://img.shields.io/pypi/v/Plim.svg :target: https://crate.io/packages/Plim -.. image:: https://pypip.in/d/Plim/badge.png - :target: https://crate.io/packages/Plim +.. image:: https://requires.io/github/avanov/Plim/requirements.svg?branch=master + :target: https://requires.io/github/avanov/Plim/requirements/?branch=master + :alt: Requirements Status -.. image:: https://api.travis-ci.org/avanov/Plim.png - :target: https://travis-ci.org/avanov/Plim +.. image:: https://img.shields.io/pypi/dm/Plim.svg + :target: https://crate.io/packages/Plim -.. image:: https://coveralls.io/repos/avanov/Plim/badge.png?branch=develop - :target: https://coveralls.io/r/avanov/Plim?branch=develop +.. image:: https://github.com/avanov/Plim/workflows/CI/badge.svg?branch=develop + :target: https://github.com/avanov/Plim/actions?query=branch%3Adevelop -.. image:: https://gemnasium.com/avanov/Plim.svg - :target: https://gemnasium.com/avanov/Plim +.. image:: https://coveralls.io/repos/github/avanov/Plim/badge.svg?branch=develop + :target: https://coveralls.io/github/avanov/Plim?branch=develop Plim is a Python port of `Ruby's Slim template language `_ diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..22c3847 --- /dev/null +++ b/default.nix @@ -0,0 +1,67 @@ +# https://nixos.wiki/wiki/Development_environment_with_nix-shell +{ pkgs ? (import ./nixpkgs).pkgs +, pyVersion ? "310" +}: + +let + +python = pkgs."python${pyVersion}Full"; +pythonPkgs = pkgs."python${pyVersion}Packages"; + +devEnv = pkgs.mkShellNoCC { + name = "plim-devenv"; + + # The packages in the `buildInputs` list will be added to the PATH in our shell + # Python-specific guide: + # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md + nativeBuildInputs = with pkgs; [ + # see https://nixos.org/nixos/packages.html + # Python distribution + python + pythonPkgs.virtualenv + pythonPkgs.wheel + pythonPkgs.twine + pythonPkgs.coveralls + + nodejs + nodePackages.npm + taglib + ncurses + libxml2 + libxslt + libzip + zlib + # root CA certificates + cacert + which + ]; + shellHook = '' + # set SOURCE_DATE_EPOCH so that we can use python wheels + export SOURCE_DATE_EPOCH=$(date +%s) + + VENV_DIR=$PWD/.venv + + export PATH=$VENV_DIR/bin:$PATH + export PYTHONPATH="" + export LANG=en_GB.UTF-8 + + # https://python-poetry.org/docs/configuration/ + export PIP_CACHE_DIR="$PWD/.local/pip-cache${pyVersion}" + + # Setup virtualenv + if [ ! -d $VENV_DIR ]; then + virtualenv $PWD/.venv + $VENV_DIR/bin/python -m pip install -e $PWD + $VENV_DIR/bin/python -m pip install -r $PWD/requirements.txt + fi + + if [ ! -d $PWD/node_modules ]; then + npm install stylus + fi + ''; +}; + +in +{ + inherit devEnv; +} diff --git a/docs/cli.rst b/docs/cli.rst index 2c00717..e819aaf 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -9,15 +9,22 @@ source files into Mako templates. .. code-block:: shell $ plimc -h - usage: plimc [-h] [--encoding ENCODING] source target + usage: plimc [-h] [-o OUTPUT] [-e ENCODING] [-p PREPROCESSOR] [-H] [-V] source Compile plim source files into mako files. positional arguments: source path to source plim template - target path to target mako template optional arguments: -h, --help show this help message and exit - --encoding ENCODING source file encoding + -o OUTPUT, --output OUTPUT + write result to FILE. + -e ENCODING, --encoding ENCODING + content encoding + -p PREPROCESSOR, --preprocessor PREPROCESSOR + Preprocessor instance that will be used for parsing + the template + -H, --html Render HTML output instead of Mako template + -V, --version show program's version number and exit diff --git a/docs/conf.py b/docs/conf.py index a0803bb..56ce1b9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = '0.9' +version = '1.0' # The full version, including alpha/beta/rc tags. -release = '0.9.12' +release = '1.0.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/differences.rst b/docs/differences.rst index 5b4ad62..c899ff6 100644 --- a/docs/differences.rst +++ b/docs/differences.rst @@ -61,7 +61,7 @@ Plim is *not the exact* port of Slim. Here is the full list of differences. #. In Plim, all html tags **MUST** be written in lowercase. This restriction was introduced to support - :ref:`Implicit Litaral Blocks ` feature. + :ref:`Implicit Literal Blocks ` feature. .. code-block:: slim diff --git a/docs/frameworks.rst b/docs/frameworks.rst index 4cc2459..638b98a 100644 --- a/docs/frameworks.rst +++ b/docs/frameworks.rst @@ -28,15 +28,15 @@ settings dictionary. The default prefix is 'mako.'. Flask ====== -The following code snippet would get Flask working with plim: +First install the flask_mako package. The following code snippet would get Flask working with plim: .. code-block:: python from flask import Flask - from flask.ext.mako import MakoTemplates, render_template + from flask_mako import MakoTemplates, render_template from plim import preprocessor - app = Flask(__name__) + app = Flask(__name__, template_folder='.') mako = MakoTemplates(app) app.config['MAKO_PREPROCESSOR'] = preprocessor @@ -47,6 +47,7 @@ The following code snippet would get Flask working with plim: if __name__ == "__main__": app.run(debug=True) + With hello.html in templates dir: .. code-block:: html diff --git a/docs/index.rst b/docs/index.rst index efe371d..db88e7f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -38,12 +38,12 @@ Tests ======= Plim provides an extensive test suite based on -`nosetests `_. +`pytest `_. You can run the tests with the following command .. code-block:: bash - python setup.py nosetests + python -m pytest Coverage statistics are `available online `_. diff --git a/docs/locale/differences.pot b/docs/locale/differences.pot index c453d86..3052d6c 100644 --- a/docs/locale/differences.pot +++ b/docs/locale/differences.pot @@ -58,7 +58,7 @@ msgstr "" #: ../differences.rst:63 # 2a470b5d41b548dda64bed052f282a56 -msgid "This restriction was introduced to support :ref:`Implicit Litaral Blocks ` feature." +msgid "This restriction was introduced to support :ref:`Implicit Literal Blocks ` feature." msgstr "" #: ../differences.rst:79 diff --git a/docs/locale/zh_CN/LC_MESSAGES/differences.po b/docs/locale/zh_CN/LC_MESSAGES/differences.po index 2f2ee41..fb9d0cf 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/differences.po +++ b/docs/locale/zh_CN/LC_MESSAGES/differences.po @@ -65,10 +65,10 @@ msgstr "Plim 中,所有 HTML 标签 **必须** 完全小写:" #: ../differences.rst:63 msgid "" -"This restriction was introduced to support :ref:`Implicit Litaral Blocks " +"This restriction was introduced to support :ref:`Implicit Literal Blocks " "` feature." msgstr "" -"该限制是为了提供 :ref:`隐式纯文本块(Implicit Litaral Blocks) ` 功能。" +"该限制是为了提供 :ref:`隐式纯文本块(Implicit Literal Blocks) ` 功能。" #: ../differences.rst:79 msgid "" diff --git a/nixpkgs/default.nix b/nixpkgs/default.nix new file mode 100644 index 0000000..6fced31 --- /dev/null +++ b/nixpkgs/default.nix @@ -0,0 +1,12 @@ +let + +common-src = builtins.fetchTarball { + name = "common-2022-09-15"; + url = https://github.com/avanov/nix-common/archive/6e47c05632c781e0279f4b4609fb4125e4e7bf67.tar.gz; + # Hash obtained using `nix-prefetch-url --unpack ` + sha256 = "sha256:1av8r2wn4nqwldkkmij4pig9x4nhii7x053i0bd1ngi66kxdkxhr"; +}; + +in + +import common-src { projectOverlays = []; } diff --git a/package.json b/package.json new file mode 100644 index 0000000..29fb5f0 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "stylus": "^0.59.0" + } +} diff --git a/plim/adapters/babelplugin.py b/plim/adapters/babelplugin.py index 9a3c4a8..24f94da 100644 --- a/plim/adapters/babelplugin.py +++ b/plim/adapters/babelplugin.py @@ -2,7 +2,7 @@ from mako.ext.babelplugin import extract as _extract_mako from .. import preprocessor_factory -from ..util import StringIO, PY3K +from ..util import StringIO def extractor_factory(preprocessor=None): @@ -22,9 +22,6 @@ def babel_extractor(fileobj, keywords, comment_tags, options): :rtype: ``iterator`` """ raw_data = fileobj.read() - if not PY3K: - encoding = options.get('input_encoding', options.get('encoding', 'utf-8')) - raw_data = raw_data.decode(encoding) data = preprocessor(raw_data) for extracted in _extract_mako(StringIO(data), keywords, comment_tags, options): yield extracted diff --git a/plim/console.py b/plim/console.py index 73df243..69bf82c 100644 --- a/plim/console.py +++ b/plim/console.py @@ -11,8 +11,6 @@ from mako.template import Template from mako.lookup import TemplateLookup -from .util import PY3K - def plimc(args=None, stdout=None): """This is the `plimc` command line utility @@ -65,7 +63,7 @@ def plimc(args=None, stdout=None): # ------------------------------------ if args.output is None: if stdout is None: - stdout = PY3K and sys.stdout.buffer or sys.stdout + stdout = sys.stdout.buffer fd = stdout content = codecs.encode(content, 'utf-8') else: diff --git a/plim/syntax.py b/plim/syntax.py index 5e2fe48..32539ab 100644 --- a/plim/syntax.py +++ b/plim/syntax.py @@ -1,23 +1,18 @@ import re from . import lexer as l -from .util import PY3K - - -if PY3K: - PARSE_IMPLICIT_LITERAL_RE = re.compile( - # Order matters - '(?P(?:' - '\$?\{|\(|\[|&.+;|[0-9]+|' - '(?:' - '[^\u0021-\u007E]' # not ASCII 33 - 126 - '|' # or - '[A-Z]' # uppercase latin letters (ASCII 65 - 90) - ')' # It is possible because TAG_RE can match only lowercase tag names - ').*)\s*' - ) -else: - from .unportable import PARSE_IMPLICIT_LITERAL_RE + +PARSE_IMPLICIT_LITERAL_RE = re.compile( + # Order matters + '(?P(?:' + '\$?\{|\(|\[|&.+;|[0-9]+|' + '(?:' + '[^\u0021-\u007E]' # not ASCII 33 - 126 + '|' # or + '[A-Z]' # uppercase latin letters (ASCII 65 - 90) + ')' # It is possible because TAG_RE can match only lowercase tag names + ').*)\s*' +) class BaseSyntax(object): diff --git a/plim/util.py b/plim/util.py index 4a11ac4..0f8c845 100644 --- a/plim/util.py +++ b/plim/util.py @@ -1,20 +1,10 @@ import sys - PY3K = sys.version_info >= (3, 0) -if PY3K: - from io import StringIO - - joined = lambda buf: ''.join(buf) - space_separated = lambda buf: ' '.join(buf) - u = str - MAXSIZE = sys.maxsize - -else: - from StringIO import StringIO +from io import StringIO - joined = lambda buf: u('').join(buf) - space_separated = lambda buf: u(' ').join(buf) - u = unicode - MAXSIZE = sys.maxint +joined = lambda buf: ''.join(buf) +space_separated = lambda buf: ' '.join(buf) +u = str +MAXSIZE = sys.maxsize diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..cb53537 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,26 @@ +# Can also be defined in setup.cfg or tox.ini files, but +# searching stops when the first [pytest] section is found in any of these files. +# There is no merging of configuration values from multiple files. +# Read more on https://pytest.org/latest/customize.html +# ------------------------------------------------------------------------------- +[pytest] +# This would tell py.test to not recurse into typical sphinx-build directories or +# into any tmp prefixed directory. +#https://docs.pytest.org/en/latest/reference.html#confval-norecursedirs +norecursedirs = _build build dist tmp* *.egg* frontend* docs* deploy* + +# One or more Glob-style file patterns determining which python files are considered +# as test modules. +python_files = test_*.py *_test.py *_tests.py *_t.py + +# https://docs.pytest.org/en/latest/reference.html#confval-python_classes +python_classes = + Test* + *Tests + +# https://docs.pytest.org/en/latest/reference.html#confval-testpaths +testpaths = + tests + +# use coverage plugin +addopts = -s diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..a387b08 --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,3 @@ +pytest +coverage +pytest-cov \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6587d0d..bfec571 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ Mako>=0.9.0 babel>=1.3 -# We use reStructuredText (docutils' component) for both supporting +# We use reStructuredText (docutils component) for both supporting # the "-rest" extension and project documenting. So, ensure that the docutils # get installed or upgraded on the target machine docutils>=0.3 diff --git a/setup.cfg b/setup.cfg index 30c4dd2..27a5a42 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,24 @@ -[nosetests] -verbose=True -verbosity=3 -detailed-errors=1 -with-coverage=True -cover-package=plim -pdb-failures=False -nocapture=True \ No newline at end of file +[mypy] +warn_unused_ignores = true +follow_imports = normal +show_error_context = true +warn_incomplete_stub = true +ignore_missing_imports = true +check_untyped_defs = true +cache_dir = ./local/mypy-cache +warn_redundant_casts = true +warn_unused_configs = true +strict_optional = true +strict_equality = true + +[coverage:report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + +ignore_errors = True + +[coverage:run] +source = + plim diff --git a/setup.py b/setup.py index cf7fd96..47043cc 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup -PY3K = sys.version_info >= (3,0) +PY3K = sys.version_info >= (3, 0) here = lambda path: os.path.join(os.path.abspath(os.path.dirname(__file__)), path) @@ -37,14 +37,14 @@ def read(*filenames, **kwargs): setup( name='Plim', - version='0.9.12', - packages=find_packages(exclude=['tests']), + version='1.0.0', + packages=find_packages(exclude=['tests', 'nixpkgs', 'node_modules']), install_requires=requires, - setup_requires=['nose>=1.1.2'], - tests_require=['coverage'], + setup_requires=[], + tests_require=['pytest', 'coverage'], package_data={ # If any package contains *.txt or *.rst files, include them - '':['*.txt', '*.rst',] + '': ['*.txt', '*.rst'] }, include_package_data=True, @@ -67,7 +67,7 @@ def read(*filenames, **kwargs): download_url="https://github.com/avanov/Plim", keywords="mako templates ruby slim jade pyjade pyramid flask haml pyhaml", classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Framework :: Pylons', 'Framework :: Pyramid', @@ -79,7 +79,6 @@ def read(*filenames, **kwargs): 'Operating System :: Microsoft', 'Operating System :: POSIX', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..3bc8ba6 --- /dev/null +++ b/shell.nix @@ -0,0 +1 @@ +{}: (import ./default.nix {}).devEnv diff --git a/tests/fixtures/reST_result.mako b/tests/fixtures/reST_result.mako index c9e2cf5..626087a 100644 --- a/tests/fixtures/reST_result.mako +++ b/tests/fixtures/reST_result.mako @@ -4,7 +4,7 @@ -Info:See <http://docutils.sf.net/rst.html> for introductory docs. +Info:See <http://docutils.sf.net/rst.html> for introductory docs. Author: David Goodger <goodger@python.org> @@ -12,7 +12,7 @@ 2011-06-17 Revision: 7056 -Description:This is a "docinfo block", or bibliographic field list +Description:This is a "docinfo block", or bibliographic field list @@ -130,10 +130,10 @@ lines can be wrapped with continuation lines. Footnote - + @@ -177,8 +177,8 @@ used to separate indentation contexts)

emphasis; strong emphasis; interpreted text; interpreted text with role; inline literal text; standalone hyperlink, http://docutils.sourceforge.net; named reference, reStructuredText; -anonymous reference; footnote reference, [1]; citation reference, -[CIT2002]; like an inline directive; inline internal target.

+anonymous reference; footnote reference, [1]; citation reference, +[CIT2002]; like an inline directive; inline internal target.

Directive Quick Reference

diff --git a/tests/test_cli.py b/tests/test_cli.py index 38b822a..0cc9492 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -16,12 +16,8 @@ class TestCLI(TestCaseBase): def setUp(self): super(TestCLI, self).setUp() self.mako_syntax = syntax.Mako() - if PY3K: - from io import BytesIO - self.stdout = BytesIO() - else: - from StringIO import StringIO - self.stdout = StringIO() + from io import BytesIO + self.stdout = BytesIO() def test_cli_mako_output(self): plimc(['tests/fixtures/unicode_attributes_test.plim'], stdout=self.stdout)
-
[1]Manually numbered or [#] auto-numbered +
[1]Manually numbered or [#] auto-numbered (even [#labelled]) or [*] auto-symbol
@@ -143,7 +143,7 @@ lines can be wrapped with continuation lines.
- +
[CIT2002]A citation.
[CIT2002]A citation.