The lektor static file content management system

Overview

Lektor

Tests master Code Coverage PyPI version PyPI - Python Version Code Style: Black node:? Join the chat at https://gitter.im/lektor/lektor

Lektor is a static website generator. It builds out an entire project from static files into many individual HTML pages and has a built-in admin UI and minimal desktop app.

To see how it works look at the top-level example/ folder, which contains a showcase of the wide variety of Lektor's features.

For a more complete example look at the lektor/lektor-website repository, which contains the sourcecode for the official lektor website.

How do I use this?

For installation instructions head to the official documentation:

Want to develop on Lektor?

This gets you started (assuming you have Python, pip, Make and pre-commit installed):

$ git clone https://github.com/lektor/lektor
$ cd lektor
$ virtualenv venv
$ . venv/bin/activate
$ pip install --editable .
$ make build-js
$ pre-commit install
$ export LEKTOR_DEV=1
$ cp -r example example-project
$ lektor --project example-project server

If you want to run the test suite (you'll need tox installed):

$ tox
Issues
  • Video thumbnailing support using ffmpeg

    Video thumbnailing support using ffmpeg

    I'm using short video clips quite a bit with Lektor and sometimes I want to thumbnail them. This PR adds both thumbnailing and some basic metadata support.

    Example

    {% set video = this.attachments.videos.first() %}
    <img src="{{ video.thumbnail(250, 250)|url }}">
    <img src="{{ video.thumbnail(250, 250, crop=True)|url }}">
    

    The full function signature is:

    .thumbnail(width, height=None, seek=None, crop=False, quality=None)
    

    The parameters are the same as for images, but the seek parameter is new. seek is a timedelta offset for when image should be captured (default is halfway in).

    I've also added some basic metadata support:

    {{ video.width }}
    {{ video.height }}
    {{ video.duration }} (timedelta)
    

    (I haven't made the test cases yet, as I wanted some initial feedback)

    opened by runfalk 33
  • PR: Move to github actions

    PR: Move to github actions

    Todo

    • [x] Add caching for pip -> https://github.com/actions/cache/blob/master/examples.md#python---pip
    • [x] Add caching for node

    Issue(s) Resolved

    Fixes #733

    Related Issues / Links

    opened by goanpeca 32
  • PR: Themes

    PR: Themes

    #226

    Hi, This is a POC of themes support, I follow the advice in https://github.com/lektor/lektor/issues/226#issuecomment-226142885 and implement it in a way very similar to Hugo themes.

    Themes could be installed in the themes directory, It will look like this:

    project
    ├── assets
    ├── models
    ├── content
    ...
    └── themes
        └── lektor-theme-nix
            ├── assets
            ├── models
            └── templates
    

    Many themes could be added and the variable theme in .lektorprojectwill define the theme to be loaded:

    [project]
      theme = lektor-theme-nix
    

    Themes could provide templates, assets, and models (also flowdocks)

    And atheme_settings section in .lektorproject file could be used for parametrize themes:

    [theme_settings]
      name = "Rafael Laverde
      email = "[email protected]"
      about = ""
      profilepicture = "img/image.jpg"
    

    And those settings will be accessed in templates through the config env variable:

    {{ config.theme_settings.name }}


    This is working? Yep, I'm using it to build my personal website, you could take a look at how the structure look like: https://github.com/rlaverde/rlaverde

    I also did a theme https://github.com/rlaverde/lektor-theme-nix (based in an Hugo theme )

    I think this PR is only missing tests, but there's a lot of stuff to do to:

    • Documentation of how to create a theme
    • A better way to create index.html and 404.html pages
    • A repo to track all themes
    • A site for displaying themes previous
    • A more complete example project that will be used for themes as a guide
    • A command to generate the basic structure of a theme (lektor new theme)
    • Define a file (theme.ini) to contain metadata of the theme: name, author, version, lektor-required-version, keywords...
    • ...
    opened by rlaverde 30
  • Installer broken with virtualenv 20.x

    Installer broken with virtualenv 20.x

    I tried installing Lektor on Linux via the installer script at https://www.getlektor.com/install.sh. This resulted in the following error messages:

    /usr/bin/python: can't open file './src/virtualenv.py': [Errno 2] No such file or directory
    /usr/bin/python: can't open file './virtualenv.py': [Errno 2] No such file or directory
    

    It seems the internal structure of the virtualenv package changed again. If I modify the installer script to force an older version of virtualenv, it works again:

    VENV_URL = "https://pypi.org/pypi/virtualenv/16.7.9/json"
    
    opened by mthuurne 29
  • Problem installing Lektor v2.0 dmg

    Problem installing Lektor v2.0 dmg

    I've downloaded the dmg from the lektor website and tried the following:

    1. Open Finder and navigate to Downloads
    2. Open OS X Console, clear it and insert marker
    3. Double-click Lektor.dmg
    4. Drag to Applications (progress bar appears, no errors)
    5. Open Applications in Finder
    6. Double-click Lektor.app
    7. OS X errors appears saying “Lektor.app” is damaged and can’t be opened. You should move it to the Trash.

    Console shows the following log messages right after the marker.

    11/04/16 16:42:16,148 CoreServicesUIAgent[353]: Error -60005 creating authorization
    11/04/16 16:42:18,382 diskimages-helper[1004]: *** -[NSMachPort handlePortMessage:]: dropping incoming DO message because the connection is invalid
    11/04/16 16:42:23,334 lsd[235]: LaunchServices: Could not store lsd-identifiers file at /private/var/db/lsd/com.apple.lsdschemes.plist
    11/04/16 16:42:27,297 lsd[235]: LaunchServices: Could not store lsd-identifiers file at /private/var/db/lsd/com.apple.lsdschemes.plist
    11/04/16 16:42:27,326 CoreServicesUIAgent[353]: Error -60005 creating authorization
    11/04/16 16:42:29,133 CoreServicesUIAgent[353]: Error SecAssessmentCreate: The operation couldn’t be completed. (OSStatus error -67061.)
    11/04/16 16:42:32,947 com.apple.xpc.launchd[1]: (com.apple.xpc.launchd.oneshot.0x1000001b.Electron[1006]) Service exited due to signal: Killed: 9
    11/04/16 16:42:32,953 lsd[235]: LaunchServices: Could not store lsd-identifiers file at /private/var/db/lsd/com.apple.lsdschemes.plist
    11/04/16 16:42:32,978 lsd[235]: LaunchServices: Could not store lsd-identifiers file at /private/var/db/lsd/com.apple.lsdschemes.plist
    
    opened by hackebrot 25
  • Add black/isort to the CI and codebase

    Add black/isort to the CI and codebase

    What does everyone think about adding pre-commit with black/isort/flake8 to the codebase? It would make everything look more consistent and would enforce the style at the CI level. flake8 would also get rid of some common bugs.

    opened by skorokithakis 19
  • Allow process_image to accept extra parameters to ImageMagick

    Allow process_image to accept extra parameters to ImageMagick

    I have found that I can halve my image size if I pass -strip to ImageMagick. Due to my thumbnail plugin being what it is, I would greatly benefit by process_image being able to accept a list of extra parameters to pass to ImageMagick.

    It would not be appropriate to include these parameters in process_image in mainline because not everybody wants thumbnail-quality, but for my plugin they're ideal. Would this be a desirable PR to open? If so, I can submit it ASAP.

    What do you think, @nixjdm?

    opened by skorokithakis 19
  • Port to Python 3

    Port to Python 3

    closes #142

    opened by ChillarAnand 19
  • Admin broken on master

    Admin broken on master

    I get this on master:

    Uncaught (in promise) TypeError: Cannot read property 'props' of undefined
        at Object.isActive (http://localhost:5000/admin/static/gen/app.js:9182:27)
        at http://localhost:5000/admin/static/gen/app.js:9241:29
        at Array.map (native)
        at Object.render (http://localhost:5000/admin/static/gen/app.js:9232:44)
        at http://localhost:5000/admin/static/gen/vendor.js:16301:22
        at measureLifeCyclePerf (http://localhost:5000/admin/static/gen/vendor.js:15581:13)
        at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (http://localhost:5000/admin/static/gen/vendor.js:16300:26)
        at ReactCompositeComponentWrapper._renderValidatedComponent (http://localhost:5000/admin/static/gen/vendor.js:16327:33)
        at ReactCompositeComponentWrapper.performInitialMount (http://localhost:5000/admin/static/gen/vendor.js:15867:31)
        at ReactCompositeComponentWrapper.mountComponent (http://localhost:5000/admin/static/gen/vendor.js:15763:22)
    

    Oddly enough the generated code seems completely wrong:

    	  isActive: function isActive(field) {
    	    var value = undefined.props.value;
    	    if (value == null) {
    	      value = undefined.props.placeholder;
    	      if (value == null) {
    	        return false;
    	      }
    	    }
    

    Not sure why this is undefined.props; the source says this.props.

    bug 
    opened by mitsuhiko 19
  • Relative URLs, fixes #713

    Relative URLs, fixes #713

    Issue(s) Resolved

    Fixes #713

    Description of Changes

    • [x] Wrote at least one-line docstrings (for any new functions)
    • [x] Added unit test(s) covering the changes (if testable)
    • [ ] Included a screenshot or animation (if affecting the UI, see Licecap)
    • [ ] Link to corresponding documentation pull request for getlektor.com

    Actual relative URLs that omit unnecessary folder traversing.

    Example: /articles/2019/07/brownies -> link to -> /articles/2019/07/brownies/image-gallery

    Previous output: ../../../../articles/2019/07/brownies/image-gallery/ Ouput with this PR: image-gallery/

    Note: Resources in the same directory are linked without ./ in front. With the only exception if the link target is the same. /blog/ -> link to /blog/ will result in ./ -> link to /blog/a.jpg will result in a.jpg

    Tiny URLs for all :)

    opened by relikd 18
  • rsync --delete-delay is not supported on macOS

    rsync --delete-delay is not supported on macOS

    https://github.com/lektor/lektor/blob/0ce8fd42affd53c1e45a8aa25c76f1554e3bb2c8/lektor/publisher.py#L187-L188

    --delete                delete extraneous files from dest dirs
    --delete-before         receiver deletes before transfer (default)
    --delete-during         receiver deletes during xfer, not before
    --delete-after          receiver deletes after transfer, not before
    --delete-excluded       also delete excluded files from dest dirs
    

    ... and since we are on the topic of rsync: I'd like to suggest to add support for local filesystem sync (e.g., if you are working on the same machine on which the web service is running). Currently providing a rsync:///absolut/path will crash Lektor. (haha, I have the same scenario as #699, currently using a custom plugin for that)

    ... and yet another request: I would welcome the addition of a dry-run option to see what changes exist. :)

    ... also: add --no-motd? – to omit the first few lines? =)

    opened by relikd 1
  • Support newer mistune versions in addition to older ones

    Support newer mistune versions in addition to older ones

    Description of Changes

    It looks like lepture has been busy and mistune 2.0.0 is about to be released, there is already some software that depends on its alpha/rc versions and rather than backporting that, it makes more sense to prepare Lektor to be compatible with the newer version.

    This patch aims to introduce minimal changes to achieve that while keeping compatibility with mistune 0.8.X.

    As a curiosity and the reason why I personally am interested in upstreaming these changes is being able to use md2gemini from Lektor with a plugin I just published today: https://pypi.org/project/lektor-gemini-capsule/ which effectively turns Lektor into a dual format (HTML and Gemini) publishing software.

    With this patch it works wonders!

    opened by evilham 3
  • Cannot install on Windows 10 due to incompatibility with python 3.10

    Cannot install on Windows 10 due to incompatibility with python 3.10

    I am unable to install lektor on a new Windows 10 with python 3.10.0

    I tried both the official way as well as pipx with no luck. I get the same error.

    Any idea on what could be wrong or what I could be doing wrong here?

    PS C:\Users\animesh> pipx install lektor
      installed package lektor 3.2.2, Python 3.10.0
      These apps are now globally available
        - lektor.exe
    done! ✨ 🌟 ✨
    PS C:\Users\animesh> lektor
    Traceback (most recent call last):
      File "C:\Users\animesh\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "C:\Users\animesh\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
        exec(code, run_globals)
      File "C:\Users\animesh\.local\bin\lektor.exe\__main__.py", line 4, in <module>
      File "C:\Users\animesh\.local\pipx\venvs\lektor\lib\site-packages\lektor\cli.py", line 13, in <module>
        from .project import Project
      File "C:\Users\animesh\.local\pipx\venvs\lektor\lib\site-packages\lektor\project.py", line 5, in <module>
        from inifile import IniFile
      File "C:\Users\animesh\.local\pipx\venvs\lektor\lib\site-packages\inifile.py", line 7, in <module>
        from collections import MutableMapping, OrderedDict
    ImportError: cannot import name 'MutableMapping' from 'collections' (C:\Users\animesh\AppData\Local\Programs\Python\Python310\lib\collections\__init__.py)
    PS C:\Users\animesh>
    
    opened by anmsh 9
  • fix flaky windows test

    fix flaky windows test

    The CI tests that try to install the (non-Python) dependencies imagemagick and ffmpeg fail pretty regularly when trying to install those two packages with chocolatey. This seems to happen most often due to the imagemagick URL 404ing on us as far as I can tell. These steps are currently allowed to fail (which means that the parts of Lektor relying on those tools are not consistently tested on Windows), since those failures are not highlighting any problems in Lektor itself.

    However, it would be nice if ~~Windows didn't exist~~ we could get consistent tests on Windows as well. winget as an alternative package manager was suggested in #933, that might be worth a shot (it doesn't have ffmpeg but then the ffmpeg install doesn't seem as problematic with chocolatey).

    ci 
    opened by yagebu 1
  • Add pyupgrade pre-commit hook

    Add pyupgrade pre-commit hook

    This hook automatically updates Python files with modern syntax, e.g., f-strings and sets.

    opened by yagebu 2
  • Disable deprecated implicit thumbnail upscaling?

    Disable deprecated implicit thumbnail upscaling?

    Implicit thumbnail upscaling, as well as the crop argument to Image.thumbnail have been deprecated since release 3.2.0.

    This issue is here to make sure we don't forget to disable those features when the time is right.

    (This issue should probably be attached to the 4.0 Milestone, but I don't think that I have sufficient privileges to do so.)

    Refs: #551, #885

    opened by dairiki 1
  • Failing 22 tests

    Failing 22 tests

    When packaging lektor for openSUSE, there are quite number of tests failing:

    [   78s] =================================== FAILURES ===================================
    [   78s] _________________ test_build_continue_in_existing_nonempty_dir _________________
    [   78s] 
    [   78s] project_cli_runner = <click.testing.CliRunner object at 0x7f830b8f2908>
    [   78s] 
    [   78s]     def test_build_continue_in_existing_nonempty_dir(project_cli_runner):
    [   78s]         os.mkdir('build_dir')
    [   78s]         with open('build_dir/test', 'w'):
    [   78s]             pass
    [   78s]         result = project_cli_runner.invoke(cli, ["build", "-O", "build_dir"], input='y\n')
    [   78s]         assert "Finished prune" in result.output
    [   78s] >       assert result.exit_code == 0
    [   78s] E       assert 1 == 0
    [   78s] E         +1
    [   78s] E         -0
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_cli.py:22: AssertionError
    [   78s] __________________________________ test_build __________________________________
    [   78s] 
    [   78s] project_cli_runner = <click.testing.CliRunner object at 0x7f830bafda58>
    [   78s] 
    [   78s]     def test_build(project_cli_runner):
    [   78s]         result = project_cli_runner.invoke(cli, ["build"])
    [   78s]         assert "files or folders already exist" not in result.output # No warning on fresh build
    [   78s] >       assert result.exit_code == 0
    [   78s] E       assert 1 == 0
    [   78s] E         +1
    [   78s] E         -0
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_cli.py:58: AssertionError
    [   78s] __________________________ test_deprecated_build_flag __________________________
    [   78s] 
    [   78s] project_cli_runner = <click.testing.CliRunner object at 0x7f830b8550b8>
    [   78s] mocker = <pytest_mock.plugin.MockerFixture object at 0x7f830b8551d0>
    [   78s] 
    [   78s]     def test_deprecated_build_flag(project_cli_runner, mocker):
    [   78s]         mock_builder = mocker.patch('lektor.builder.Builder')
    [   78s]         mock_builder.return_value.build_all.return_value = 0
    [   78s]         with warnings.catch_warnings(record=True) as w:
    [   78s]             result = project_cli_runner.invoke(cli, ["build", "--build-flag", "webpack"])
    [   78s]             assert result.exit_code == 0
    [   78s]             assert mock_builder.call_args[1]["extra_flags"] == ("webpack",)
    [   78s] >           assert len(w) == 1
    [   78s] E           assert 6 == 1
    [   78s] E             +6
    [   78s] E             -1
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_cli.py:86: AssertionError
    [   78s] ________________________ test_thumbnail_dimensions_real ________________________
    [   78s] 
    [   78s] builder = <lektor.builder.Builder object at 0x7f830b78da90>
    [   78s] 
    [   78s]     def test_thumbnail_dimensions_real(builder):
    [   78s]         builder.build_all()
    [   78s]         for t, dimensions in _THUMBNAILS.items():
    [   78s]             image_file = os.path.join(builder.destination_path, t)
    [   78s] >           with open(image_file, 'rb') as f:
    [   78s] E           FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-abuild/pytest-0/test_thumbnail_dimensions_real0/output/[email protected]'
    [   78s] 
    [   78s] tests/test_images.py:155: FileNotFoundError
    [   78s] ___________________________ test_thumbnails_similar ____________________________
    [   78s] 
    [   78s] builder = <lektor.builder.Builder object at 0x7f830b86b128>
    [   78s] 
    [   78s]     def test_thumbnails_similar(builder):
    [   78s]         builder.build_all()
    [   78s]         hashes = []
    [   78s]         for t in _SIMILAR_THUMBNAILS:
    [   78s]             image_file = os.path.join(builder.destination_path, t)
    [   78s] >           with open(image_file, 'rb') as f:
    [   78s] E           FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-abuild/pytest-0/test_thumbnails_similar0/output/[email protected]'
    [   78s] 
    [   78s] tests/test_images.py:165: FileNotFoundError
    [   78s] __________________________ test_thumbnails_differing ___________________________
    [   78s] 
    [   78s] builder = <lektor.builder.Builder object at 0x7f830b5dec18>
    [   78s] 
    [   78s]     def test_thumbnails_differing(builder):
    [   78s]         builder.build_all()
    [   78s]         hashes = []
    [   78s]         for t in _DIFFERING_THUMBNAILS:
    [   78s]             image_file = os.path.join(builder.destination_path, t)
    [   78s] >           with open(image_file, 'rb') as f:
    [   78s] E           FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-abuild/pytest-0/test_thumbnails_differing0/output/[email protected]0x100_crop.jpg'
    [   78s] 
    [   78s] tests/test_images.py:178: FileNotFoundError
    [   78s] ____________________________ test_thumbnail_quality ____________________________
    [   78s] 
    [   78s] builder = <lektor.builder.Builder object at 0x7f830b4f5fd0>
    [   78s] 
    [   78s]     def test_thumbnail_quality(builder):
    [   78s]         builder.build_all()
    [   78s]         image_file = os.path.join(builder.destination_path, '[email protected]_q20.jpg')
    [   78s]         # See if the image file with said quality suffix exists
    [   78s] >       assert os.path.isfile(image_file)
    [   78s] E       AssertionError: assert False
    [   78s] E        +  where False = <function isfile at 0x7f830e4ada60>('/tmp/pytest-of-abuild/pytest-0/test_thumbnail_quality0/output/[email protected]_q20.jpg')
    [   78s] E        +    where <function isfile at 0x7f830e4ada60> = <module 'posixpath' from '/usr/lib64/python3.6/posixpath.py'>.isfile
    [   78s] E        +      where <module 'posixpath' from '/usr/lib64/python3.6/posixpath.py'> = os.path
    [   78s] 
    [   78s] tests/test_images.py:190: AssertionError
    [   78s] ________________ test_plugin_build_events_via_cli[before_prune] ________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830ba2f160>, 'before_prune', <click.testing.CliRunner object at 0x7f830ba2f7f0>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpt_4nf6wh/packages/event-test0
    [   78s] Installing collected packages: lektor-event-test0
    [   78s]   Running setup.py develop for lektor-event-test0
    [   78s] Successfully installed lektor-event-test0
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ________________ test_plugin_build_events_via_cli[after_prune] _________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830ba2f518>, 'after_prune', <click.testing.CliRunner object at 0x7f830ba2f3c8>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpj3etlh5r/packages/event-test1
    [   78s] Installing collected packages: lektor-event-test1
    [   78s]   Running setup.py develop for lektor-event-test1
    [   78s] Successfully installed lektor-event-test1
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] _________________ test_plugin_build_events_via_cli[setup_env] __________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b71dfd0>, 'setup_env', <click.testing.CliRunner object at 0x7f830b71def0>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpw6zqeouf/packages/event-test2
    [   78s] Installing collected packages: lektor-event-test2
    [   78s]   Running setup.py develop for lektor-event-test2
    [   78s] Successfully installed lektor-event-test2
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ________________ test_plugin_build_events_via_cli[before_build] ________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b87d160>, 'before_build', <click.testing.CliRunner object at 0x7f830b87d860>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpdfozoou3/packages/event-test3
    [   78s] Installing collected packages: lektor-event-test3
    [   78s]   Running setup.py develop for lektor-event-test3
    [   78s] Successfully installed lektor-event-test3
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ______________ test_plugin_build_events_via_cli[before_build_all] ______________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b6b9b70>, 'before_build_all', <click.testing.CliRunner object at 0x7f830b6b9198>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmp4c55uhlv/packages/event-test4
    [   78s] Installing collected packages: lektor-event-test4
    [   78s]   Running setup.py develop for lektor-event-test4
    [   78s] Successfully installed lektor-event-test4
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ________________ test_plugin_build_events_via_cli[after_build] _________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b731cf8>, 'after_build', <click.testing.CliRunner object at 0x7f830b731c50>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpiewr_sc4/packages/event-test5
    [   78s] Installing collected packages: lektor-event-test5
    [   78s]   Running setup.py develop for lektor-event-test5
    [   78s] Successfully installed lektor-event-test5
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ______________ test_plugin_build_events_via_cli[after_build_all] _______________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b851a20>, 'after_build_all', <click.testing.CliRunner object at 0x7f830b851898>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpki871w6_/packages/event-test6
    [   78s] Installing collected packages: lektor-event-test6
    [   78s]   Running setup.py develop for lektor-event-test6
    [   78s] Successfully installed lektor-event-test6
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] _____________ test_plugin_build_events_via_cli[markdown_meta_init] _____________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b71d550>, 'markdown_meta_init', <click.testing.CliRunner object at 0x7f830b71d780>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpy0nylmu4/packages/event-test7
    [   78s] Installing collected packages: lektor-event-test7
    [   78s]   Running setup.py develop for lektor-event-test7
    [   78s] Successfully installed lektor-event-test7
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] _________ test_plugin_build_events_via_cli[markdown_meta_postprocess] __________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b74d080>, 'markdown_meta_postprocess', <click.testing.CliRunner object at 0x7f830b74d518>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpvf_q56sd/packages/event-test8
    [   78s] Installing collected packages: lektor-event-test8
    [   78s]   Running setup.py develop for lektor-event-test8
    [   78s] Successfully installed lektor-event-test8
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] __________ test_plugin_build_events_via_cli[process_template_context] __________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b706780>, 'process_template_context', <click.testing.CliRunner object at 0x7f830ba2fef0>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", build_events, indirect=True)
    [   78s]     def test_plugin_build_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         # XXX - take a closer look at result.output
    [   78s]         # The setuptools working_set that keeps track of plugin installations is initialized
    [   78s]         # at the first import of pkg_resources, and then plugins are added to the
    [   78s]         # working_set as they are loaded into Lektor. Since pytest runs a single process,
    [   78s]         # these previous plugins are never removed. So while this does test what it says it
    [   78s]         # does, it also hooks previously generated plugins. Avoiding this with a succint
    [   78s]         # teardown is currently not possible AFAICT, since setuptools provides no clear way
    [   78s]         # of removing entry_points. I choose this comment over what would be a convoluted
    [   78s]         # and very hacky teardown function. The extra computation time is negligible.
    [   78s]         # See https://github.com/pypa/setuptools/issues/1759
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:125: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmp3xay4d2e/packages/event-test9
    [   78s] Installing collected packages: lektor-event-test9
    [   78s]   Running setup.py develop for lektor-event-test9
    [   78s] Successfully installed lektor-event-test9
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ________________ test_plugin_clean_events_via_cli[before_prune] ________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830bbad780>, 'before_prune', <click.testing.CliRunner object at 0x7f830bbad860>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", clean_events, indirect=True)
    [   78s]     def test_plugin_clean_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         # See comment in test_plugin_build_events_via_cli
    [   78s]         result = cli_runner.invoke(cli, ["clean", "--yes", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:149: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpy3cw5g0e/packages/event-test0
    [   78s] Installing collected packages: lektor-event-test0
    [   78s]   Running setup.py develop for lektor-event-test0
    [   78s] Successfully installed lektor-event-test0
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ________________ test_plugin_clean_events_via_cli[after_prune] _________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b695eb8>, 'after_prune', <click.testing.CliRunner object at 0x7f830b695e10>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", clean_events, indirect=True)
    [   78s]     def test_plugin_clean_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         # See comment in test_plugin_build_events_via_cli
    [   78s]         result = cli_runner.invoke(cli, ["clean", "--yes", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:149: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpj2z9nb19/packages/event-test1
    [   78s] Installing collected packages: lektor-event-test1
    [   78s]   Running setup.py develop for lektor-event-test1
    [   78s] Successfully installed lektor-event-test1
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] _________________ test_plugin_clean_events_via_cli[setup_env] __________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b73bf98>, 'setup_env', <click.testing.CliRunner object at 0x7f830b86b160>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", clean_events, indirect=True)
    [   78s]     def test_plugin_clean_events_via_cli(scratch_project_with_plugin):
    [   78s]         """Test whether a plugin with a given event can successfully use an extra flag.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         # See comment in test_plugin_build_events_via_cli
    [   78s]         result = cli_runner.invoke(cli, ["clean", "--yes", "-f", "EXTRA"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             if PY2:
    [   78s]                 assert "{u'EXTRA': u'EXTRA'}" in hit
    [   78s]             else:
    [   78s]                 assert "{'EXTRA': 'EXTRA'}" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:149: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmp2283gvyr/packages/event-test2
    [   78s] Installing collected packages: lektor-event-test2
    [   78s]   Running setup.py develop for lektor-event-test2
    [   78s] Successfully installed lektor-event-test2
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] _____________________ test_multiple_extra_flags[setup_env] _____________________
    [   78s] 
    [   78s] scratch_project_with_plugin = (<lektor.project.Project object at 0x7f830b4b5f28>, 'setup_env', <click.testing.CliRunner object at 0x7f830b4b5390>)
    [   78s] 
    [   78s]     @pytest.mark.parametrize("scratch_project_with_plugin", ["setup_env"], indirect=True)
    [   78s]     def test_multiple_extra_flags(scratch_project_with_plugin):
    [   78s]         """Test whether setting extra_flags passes through to each plugin event.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin
    [   78s]     
    [   78s]         # See comment in test_plugin_build_events_via_cli
    [   78s]         result = cli_runner.invoke(cli, ["build", "-f", "EXTRA", "-f", "ANOTHER"])
    [   78s]         assert result.exit_code == 0
    [   78s]     
    [   78s]         # Test that the event was triggered and the current extra flag was passed.
    [   78s]         output_lines = result.output.split("\n")
    [   78s]     
    [   78s]         hits = [r for r in output_lines if "event on_{}".format(event) in r]
    [   78s]     
    [   78s]         for hit in hits:
    [   78s]             assert "EXTRA" in hit
    [   78s]             assert "ANOTHER" in hit
    [   78s]     
    [   78s] >       assert len(hits) != 0
    [   78s] E       assert 0 != 0
    [   78s] E        +  where 0 = len([])
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:187: AssertionError
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/tmpwzhw07o3/packages/event-test0
    [   78s] Installing collected packages: lektor-event-test0
    [   78s]   Attempting uninstall: lektor-event-test0
    [   78s]     Found existing installation: lektor-event-test0 0.0.0
    [   78s]     Uninstalling lektor-event-test0-0.0.0:
    [   78s]       Successfully uninstalled lektor-event-test0-0.0.0
    [   78s]   Running setup.py develop for lektor-event-test0
    [   78s] Successfully installed lektor-event-test0
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] ______________________ test_plugin_bad_params[setup_env] _______________________
    [   78s] 
    [   78s] scratch_project_with_plugin_no_params = (<lektor.project.Project object at 0x7f830b86cf98>, 'setup_env', <click.testing.CliRunner object at 0x7f830b86ccc0>)
    [   78s] 
    [   78s]     @pytest.mark.filterwarnings("ignore::DeprecationWarning")
    [   78s]     @pytest.mark.parametrize(
    [   78s]         "scratch_project_with_plugin_no_params", ["setup_env"], indirect=True
    [   78s]     )
    [   78s]     def test_plugin_bad_params(scratch_project_with_plugin_no_params):
    [   78s]         """Ensure plugins err if event hooks don't accept needed params.
    [   78s]         """
    [   78s]         proj, event, cli_runner = scratch_project_with_plugin_no_params
    [   78s]     
    [   78s]         env = proj.make_env()
    [   78s]     
    [   78s]         # extra_flags not accepted. This will work but issues a warning.
    [   78s]         with pytest.warns(DeprecationWarning):
    [   78s] >           env.plugin_controller.emit(event)
    [   78s] E           Failed: DID NOT WARN. No warnings of type (<class 'DeprecationWarning'>,) was emitted. The list of emitted warnings is: [].
    [   78s] 
    [   78s] /home/abuild/rpmbuild/BUILD/lektor-3.2.0/tests/test_plugins.py:267: Failed
    [   78s] ----------------------------- Captured stdout call -----------------------------
    [   78s] Updating packages in /home/abuild/.cache/lektor/packages/c7f18a7576b4411c493d856aadc03d2b for project
    [   78s] Defaulting to user installation because normal site-packages is not writeable
    [   78s] Obtaining file:///tmp/pytest-of-abuild/pytest-0/test_plugin_bad_params_setup_e0/scratch-proj/packages/event-test-no-params0
    [   78s] Installing collected packages: lektor-event-test-no-params0
    [   78s]   Running setup.py develop for lektor-event-test-no-params0
    [   78s] Successfully installed lektor-event-test-no-params0
    [   78s] ----------------------------- Captured stderr call -----------------------------
    [   78s] /usr/lib/python3.6/site-packages/pip/_internal/commands/install.py:235: UserWarning: Disabling all use of wheels due to the use of --build-option / --global-option / --install-option.
    [   78s]   cmdoptions.check_install_build_global(options)
    [   78s] =============================== warnings summary ===============================
    [   78s] tests/test_api.py: 1 warning
    [   78s] tests/test_builder.py: 12 warnings
    [   78s] tests/test_cli.py: 5 warnings
    [   78s] tests/test_config.py: 1 warning
    [   78s] tests/test_db.py: 18 warnings
    [   78s] tests/test_deploy.py: 18 warnings
    [   78s] tests/test_editor.py: 2 warnings
    [   78s] tests/test_environment.py: 1 warning
    [   78s] tests/test_images.py: 8 warnings
    [   78s] tests/test_pagination.py: 36 warnings
    [   78s] tests/test_plugins.py: 28 warnings
    [   78s] tests/test_prev_next_sibling.py: 2 warnings
    [   78s] tests/test_themes.py: 17 warnings
    [   78s] tests/test_types.py: 18 warnings
    [   78s] tests/test_unicode.py: 3 warnings
    [   78s] tests/test_urls.py: 30 warnings
    [   78s] tests/test_watcher.py: 1 warning
    [   78s] tests/test_webui.py: 1 warning
    [   78s]   /usr/lib/python3.6/site-packages/jinja2/environment.py:362: DeprecationWarning: The 'autoescape' extension is deprecated and will be removed in Jinja 3.1. This is built in now.
    [   78s]     self.extensions = load_extensions(self, extensions)
    [   78s] 
    [   78s] tests/test_api.py: 1 warning
    [   78s] tests/test_builder.py: 12 warnings
    [   78s] tests/test_cli.py: 5 warnings
    [   78s] tests/test_config.py: 1 warning
    [   78s] tests/test_db.py: 18 warnings
    [   78s] tests/test_deploy.py: 18 warnings
    [   78s] tests/test_editor.py: 2 warnings
    [   78s] tests/test_environment.py: 1 warning
    [   78s] tests/test_images.py: 8 warnings
    [   78s] tests/test_pagination.py: 36 warnings
    [   78s] tests/test_plugins.py: 28 warnings
    [   78s] tests/test_prev_next_sibling.py: 2 warnings
    [   78s] tests/test_themes.py: 17 warnings
    [   78s] tests/test_types.py: 18 warnings
    [   78s] tests/test_unicode.py: 3 warnings
    [   78s] tests/test_urls.py: 30 warnings
    [   78s] tests/test_watcher.py: 1 warning
    [   78s] tests/test_webui.py: 1 warning
    [   78s]   /usr/lib/python3.6/site-packages/jinja2/environment.py:362: DeprecationWarning: The 'with' extension is deprecated and will be removed in Jinja 3.1. This is built in now.
    [   78s]     self.extensions = load_extensions(self, extensions)
    [   78s] 
    [   78s] tests/test_api.py: 1 warning
    [   78s] tests/test_builder.py: 12 warnings
    [   78s] tests/test_cli.py: 5 warnings
    [   78s] tests/test_config.py: 1 warning
    [   78s] tests/test_db.py: 18 warnings
    [   78s] tests/test_deploy.py: 18 warnings
    [   78s] tests/test_editor.py: 2 warnings
    [   78s] tests/test_environment.py: 1 warning
    [   78s] tests/test_images.py: 8 warnings
    [   78s] tests/test_pagination.py: 36 warnings
    [   78s] tests/test_plugins.py: 28 warnings
    [   78s] tests/test_prev_next_sibling.py: 2 warnings
    [   78s] tests/test_themes.py: 17 warnings
    [   78s] tests/test_types.py: 18 warnings
    [   78s] tests/test_unicode.py: 3 warnings
    [   78s] tests/test_urls.py: 30 warnings
    [   78s] tests/test_watcher.py: 1 warning
    [   78s] tests/test_webui.py: 1 warning
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/environment.py:448: DeprecationWarning: 'contextfilter' is renamed to 'pass_context', the old name will be removed in Jinja 3.1.
    [   78s]     lambda ctx, *a, **kw: url_to(*a, **kw)),
    [   78s] 
    [   78s] tests/test_api.py: 1 warning
    [   78s] tests/test_builder.py: 12 warnings
    [   78s] tests/test_cli.py: 5 warnings
    [   78s] tests/test_config.py: 1 warning
    [   78s] tests/test_db.py: 18 warnings
    [   78s] tests/test_deploy.py: 18 warnings
    [   78s] tests/test_editor.py: 2 warnings
    [   78s] tests/test_environment.py: 1 warning
    [   78s] tests/test_images.py: 8 warnings
    [   78s] tests/test_pagination.py: 36 warnings
    [   78s] tests/test_plugins.py: 28 warnings
    [   78s] tests/test_prev_next_sibling.py: 2 warnings
    [   78s] tests/test_themes.py: 17 warnings
    [   78s] tests/test_types.py: 18 warnings
    [   78s] tests/test_unicode.py: 3 warnings
    [   78s] tests/test_urls.py: 30 warnings
    [   78s] tests/test_watcher.py: 1 warning
    [   78s] tests/test_webui.py: 1 warning
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/environment.py:450: DeprecationWarning: 'contextfilter' is renamed to 'pass_context', the old name will be removed in Jinja 3.1.
    [   78s]     lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
    [   78s] 
    [   78s] tests/test_api.py: 1 warning
    [   78s] tests/test_builder.py: 12 warnings
    [   78s] tests/test_cli.py: 5 warnings
    [   78s] tests/test_config.py: 1 warning
    [   78s] tests/test_db.py: 18 warnings
    [   78s] tests/test_deploy.py: 18 warnings
    [   78s] tests/test_editor.py: 2 warnings
    [   78s] tests/test_environment.py: 1 warning
    [   78s] tests/test_images.py: 8 warnings
    [   78s] tests/test_pagination.py: 36 warnings
    [   78s] tests/test_plugins.py: 28 warnings
    [   78s] tests/test_prev_next_sibling.py: 2 warnings
    [   78s] tests/test_themes.py: 17 warnings
    [   78s] tests/test_types.py: 18 warnings
    [   78s] tests/test_unicode.py: 3 warnings
    [   78s] tests/test_urls.py: 30 warnings
    [   78s] tests/test_watcher.py: 1 warning
    [   78s] tests/test_webui.py: 1 warning
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/environment.py:452: DeprecationWarning: 'contextfilter' is renamed to 'pass_context', the old name will be removed in Jinja 3.1.
    [   78s]     lambda ctx, *a, **kw: Markdown(*a, **kw)),
    [   78s] 
    [   78s] tests/test_builder.py::test_basic_template_rendering
    [   78s] tests/test_cli.py::test_build_continue_in_existing_nonempty_dir
    [   78s] tests/test_cli.py::test_build
    [   78s] tests/test_images.py::test_thumbnail_dimensions_reported
    [   78s] tests/test_images.py::test_thumbnail_dimensions_real
    [   78s] tests/test_images.py::test_thumbnails_similar
    [   78s] tests/test_images.py::test_thumbnails_differing
    [   78s] tests/test_images.py::test_thumbnail_quality
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/imagetools.py:531: UserWarning: Your images are currently scaled up when the thumbnail requested is larger than the source. This default will change in the future. If you want to preserve the current behaviour, use `upscale=True`.
    [   78s]     'Your images are currently scaled up when the thumbnail requested '
    [   78s] 
    [   78s] tests/test_devcli.py: 23 warnings
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/quickstart.py:38: DeprecationWarning: 'click.get_terminal_size()' is deprecated and will be removed in Click 8.1. Use 'shutil.get_terminal_size()' instead.
    [   78s]     self.term_width = min(max(click.get_terminal_size()[0], 1), 78)
    [   78s] 
    [   78s] tests/test_webui.py::test_index_html
    [   78s] tests/test_webui.py::test_index_html
    [   78s]   /home/abuild/rpmbuild/BUILDROOT/python-Lektor-3.2.0-0.x86_64/usr/lib/python3.6/site-packages/lektor/admin/webui.py:74: DeprecationWarning: 'flask.helpers.safe_join' is deprecated and will be removed in Flask 2.1. Use 'werkzeug.utils.safe_join' instead.
    [   78s]     filename = safe_join(self.output_path, *path_list)
    [   78s] 
    [   78s] -- Docs: https://docs.pytest.org/en/stable/warnings.html
    [   78s] =========================== short test summary info ============================
    [   78s] FAILED tests/test_cli.py::test_build_continue_in_existing_nonempty_dir - asse...
    [   78s] FAILED tests/test_cli.py::test_build - assert 1 == 0
    [   78s] FAILED tests/test_cli.py::test_deprecated_build_flag - assert 6 == 1
    [   78s] FAILED tests/test_images.py::test_thumbnail_dimensions_real - FileNotFoundErr...
    [   78s] FAILED tests/test_images.py::test_thumbnails_similar - FileNotFoundError: [Er...
    [   78s] FAILED tests/test_images.py::test_thumbnails_differing - FileNotFoundError: [...
    [   78s] FAILED tests/test_images.py::test_thumbnail_quality - AssertionError: assert ...
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[before_prune]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[after_prune]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[setup_env] - a...
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[before_build]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[before_build_all]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[after_build]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[after_build_all]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[markdown_meta_init]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[markdown_meta_postprocess]
    [   78s] FAILED tests/test_plugins.py::test_plugin_build_events_via_cli[process_template_context]
    [   78s] FAILED tests/test_plugins.py::test_plugin_clean_events_via_cli[before_prune]
    [   78s] FAILED tests/test_plugins.py::test_plugin_clean_events_via_cli[after_prune]
    [   78s] FAILED tests/test_plugins.py::test_plugin_clean_events_via_cli[setup_env] - a...
    [   78s] FAILED tests/test_plugins.py::test_multiple_extra_flags[setup_env] - assert 0...
    [   78s] FAILED tests/test_plugins.py::test_plugin_bad_params[setup_env] - Failed: DID...
    [   78s] ========== 22 failed, 272 passed, 4 skipped, 1043 warnings in 47.45s ===========
    

    It is possible that I do something wrong, but it doesn't seem to me. Complete log should describe all steps taken and all packages used for building the package and running tests.

    opened by mcepl 1
  • Change recomended installation method to `pipx`

    Change recomended installation method to `pipx`

    I've installed lektor multiple times to test and contribute to Barranquilla's python community page pybaq.co and my personal page. I've also attempted to teach others how to install it (mostly beginners) with various barriers in the process.

    On some versions of ubuntu there are issues with availability of wheels for some packages. On windows there are issues when using python from the Windows Store. Many of these issues arise from trying to build everything from scratch.

    I propose the use of pipx to create an easier install. It is recommended by PyPA specifically for stand alone command line tools. It is OS independent. It is part of PyPA's codebase. It has clear documentation.

    After basic installation, lektor install script would be as simple as pipx install lektor or adding sudo pipx install lektor for ubuntu based distributions to perform a global install.

    Are there argument in favor or against? I'd take the task to update the docs on the webpage if agreed upon. (And of course, #911 has to be included for any install to work correctly without the need for alternate procedures).

    installation 
    opened by andresperezcera 14
  • url filter miss the final slash when directories are in assets

    url filter miss the final slash when directories are in assets

    URL rendered with the url filter remove the final / of directory when they are stored in assets. This cause extra 301 redirect by the web server.

    If I have an asset directory named assets/kabaal/ Both [Kabaal]({{'kabaal'|url}}) and [Kabaal]({{'kabaal/'|url}}) syntaxes render to <a href="kabaal">Kabaal</a> instead of <a href="kabaal/">Kabaal</a>.

    Even the "I know what I'm doing" syntax [Kabaal]({{'!/kabaal/'|url}}) produce an URL without the final /.

    opened by seblu 0
  • Support for yaml databags

    Support for yaml databags

    Description of Changes

    • [ ] Wrote at least one-line docstrings (for any new functions)
    • [x] Added unit test(s) covering the changes (if testable)
    • [ ] Included a screenshot or animation (if affecting the UI, see Licecap)
    • [x] Link to corresponding documentation pull request for getlektor.com

    Added support for yaml databags, and added a test case for databags in general (testing ini, json, and yaml).

    Documentation update: https://github.com/lektor/lektor-website/pull/321

    opened by e8johan 0
Releases(3.2.0)
  • 3.2.0(Aug 20, 2020)

    • Fix off-by-one error in pagination's iter_pages in the interpretation of the right_current argument, and adding an appropriate trailing None for some uses.
    • Add support for setting an output_path in the project file.
    • Replaced the slugify backend to handle unicode more effectively. This should mean greater language support, but it may produce slightly different results in some cases.
    • Several modernization and performance improvements to the admin UI
    • Improved speed of source info updates.
    • Set colorspace to sRGB for thumbnails.
    • Now stripping profiles and comments from thumbnails.
    • Added support for deleting and excluding files for the rsync deployment publisher.
    • Improved speed of flow rendering in the admin UI.
    • Bugfix to correctly calculate relative urls from slugs that contain dots.
    • Bugfix to allow negative integers in integer fields in the admin UI.
    • Improved image-heavy build speeds by reducing the amount of data extracted from EXIFs.
    • Added the ability to collapse flow elements in the admin UI.
    • Now extra_flags is passed to all plugin events.
    • Extra flags can now be passed to the clean and dev shell CLI commands.
    • Bugfix where lektor plugins reinstall triggered on_setup_env instead of just reinstalling plugins.
    • Added the ability to generate video thumbnails with ffmpeg.
    • Added mode and upscale thumbnail arguments, changing the preferred crop method to using mode. mode can be crop, fit, or stretch. upscale=False can now prevent upscaling.
    • Added a new CLI command lektor dev new-theme.
    • Made admin use full UTF-8 version of RobotoSlab. Fixes missing glyphs for some languages
    • Bumped minimum Jinja2 version to 2.11
    • Bumped filetype dependency to 1.0.7 because of API changes
    • Relative urls are now as short as possible.
    • Automatically include setup.cfg configured for universal wheels when creating plugins
    Source code(tar.gz)
    Source code(zip)
  • 3.1.2(Sep 7, 2018)

    • Fix pagination and virtual pathing for alts
    • Fixing deploy from local server in Python 3
    • Now passing server_info to publisher from local server, providing better support for plugin provided publishers.
    • Added a more full-featured example project.
    • Adding Jinja2 do extension.
    • Better new-plugin command.
    • More tests.
    • Added the ability to sort child pages in admin according to models.
    • Better image handling and info detection for JPGs and SVGs
    • Lektor can now be ran with python -m lektor
    • New plugins now come with a more full featured setup.py
    Source code(tar.gz)
    Source code(zip)
  • 3.1.1(Apr 18, 2018)

    • Better Image dimension detection.
    • Fix backwards compatibility with thumbnail generation.
    • Adding safety check when runnning new build in non-empty dir since that could delete data.
    • Adding command aliases.
    Source code(tar.gz)
    Source code(zip)
  • 3.1(Jan 29, 2018)

    3.1.0

    Release date 29th of January 2018.

    • Adding ability to use Lektor Themes.
    • Adding Markdown event hook between instantiating the Renderer and creating the Markdown Processor
    • Improving tests for GitHub deployment.
    • Added the ability to use IPython in the lektor dev shell if it's available.
    • Added ability to publish from different filesystems.
    • Adding new option to turn disable editing fields on alternatives.
    • Added automated testing for Windows.
    • Expanded automated testing environments to Python 2.7, 3.5, 3.6, & Node 6, 7, 8.
    • Windows bugfixes.
    • Improved exif image data.
    • Improved date handling in admin.
    • Make GitHub Pages branch detection case insensitive.
    • Set sqlite isolation to autocommit.
    • Fixed errors in the example project.
    • Enabling pylint and standard.js.
    • Improved image rotation.
    • Now measuring tests and pull requests with code coverage.
    • Thumbnails can now have a defined quality.
    • Moved Windows cache to local appdata.
    • README tweaks.
    • Beter translations.
    • Better file tracking in watcher.
    • Upgraded many node dependencies.
    • Upgraded from ES5 to ES6.
    • Added mp4 attachment type.
    • Bugfixes for Python 3.
    Source code(tar.gz)
    Source code(zip)
  • 3.1.0.dev1(Dec 8, 2017)

    • Added Lektor theming.
    • Fix: Potential infinite build/prune loop due to pathing issue.
    • Added markdown-lexer-config plugin hook.
    • Fix GitHub deploy on Python 3.
    • Added ability for dev shell to use IPython if it's available.
    • Added ability to publish from different filesystems.
    • Adding new option to turn on disabling of editing fields on alternatives.
    • Added automated testing for Windows.
    • Expanded automated testing environments to Python 2.7, 3.5, 3.6, & Node 6, 7, 8.
    • Windows bugfixes.
    • Improved exif image data.
    • Improved date handling in admin.
    • Make GitHub Pages branch detection case insensitive.
    • Set sqlite isolation to autocommit.
    • Fixed errors in the example project.
    • Enabling pylint and standard.js.
    • Improved image rotation.
    • Now measuring tests and pull requests with code coverage.
    • Thumbnails can now have a defined quality.
    • Moved Windows cache to local appdata.
    • README tweaks.
    • Beter translations.
    • Better file tracking in watcher.
    • Upgraded many node dependencies.
    • Upgraded from ES5 to ES6.
    • Added mp4 attachment type.
    • Bugfixes for Python 3.
    Source code(tar.gz)
    Source code(zip)
  • 3.0.1(Jun 13, 2017)

  • 3.0(Jun 13, 2017)

  • 2.4(Jun 13, 2017)

  • 2.3(May 31, 2016)

  • 2.2(Apr 12, 2016)

  • 2.1(Apr 12, 2016)

  • 2.0(Apr 10, 2016)

    • Added _discoverable system field which controls if a page should show up in children. The default is that a page is discoverable. Setting it to False means in practical terms that someone needs to know the URL as all collection operations will not return it.
    • Added for_page function to pagination that returns the pagiantion for a specific page.
    • Make pagination next_page and prev_page be None on the edges.
    • Allow plugins to provide publishers.
    • Added |markdown filter.
    • Added French translations.
    • Unicode filenames as final build artifacts are now explicitly disallowed.
    • Serve up a 404.html as an error page in the dev server.
    • Improvements to the path normalization and alt handling. This should support URL generation in more complex cases between alts now.
    • Show a clearer error message when URL generation fails because a source object is virtual (does not have a path).
    • Empty text is now still valid markdown.
    • Lektor clean now loads the plugins as well.
    • Basic support for type customization.
    • Fields that are absent in a content file from an alternative are now pulled from the primary content file.
    • Development server now resolves index.html for assets as well.
    • Markdown processing now correctly adjusts links relative to where the rendered output is rendered.
    • Added Dutch translations.
    • Added Record.get_siblings()
    • Added various utilties: build_url, join_path, parse_path
    • Added support for virtual paths and made pagination work with it.
    • Added support for Query.distinct
    • Add support for pagination url resolving on root URL.
    • Server information can now also contain extra key/value pairs that can be used by publishers to affect the processing.
    • The thumbnails will now always have the correct width and height set as an attribute.
    • added datetime type
    • added support for the process_image utility functions so that plugins can use it directly.
    • added support for included_assets and excluded_assets in the project file.
    • added Spanish translations.
    • added Japanese translations.
    • added support for discovering existing alts of sources.
    • added support for image cropping.
    • added preliminary support for publishing on windows.
    • children and attachments can now have a hidden flag configured explicitly. Attachments will also no longer inherit the hidden flag of the parent record as that is not a sensible default.
    • changed internal sqlite consistency mode to improve performance on HDDs.
    • allow SVG files to be treated as images. This is something that does not work in all situations yet (in particular thumbnailing does not actually do anything for those)
    Source code(tar.gz)
    Source code(zip)
    Lektor-2.0.dmg(65.70 MB)
  • 1.2.1(Feb 3, 2016)

  • 1.2(Feb 2, 2016)

    • Fixed an error that caused unicode characters in the project name to be mishandled in the quickstart.
    • Do not create empty folders when the quickstart skips over files.
    • Empty values for the slug field now pull in the default.
    • Corrected a bug in hashing in the FTP publisher that could cause files to not upload correctly.
    • Improved error message for when imagemagick cannot be found.
    • Fixed scrolling in the admin for firefox and some other browsers.
    • Fixed a problem with deleting large projects due to sqlite limitations.
    • Fixed admin preview of root page in firefox.
    Source code(tar.gz)
    Source code(zip)
    Lektor-1.2.dmg(66.17 MB)
  • 1.1(Dec 27, 2015)

    Fixes the following bugs:

    • Fixed a bug where resolving URL paths outside of alts did not fall back to asset resolving.
    • verbose mode now correctly displays traceback of build failures.
    • Fixed a bug that caused build failures not to be remembered.
    • Fixed a bad EXIF attribute (longitude was misspelt)
    • Use requests for URL fetching instead of urllib. This should fix some SSL errors on some Python versions.
    • Parent of page now correctly resolves to the right alt.
    • Publish from a temporary folder on the same device which solves problems on machines with /tmp on a different drive.
    Source code(tar.gz)
    Source code(zip)
    Lektor-1.1.dmg(62.51 MB)
  • 1.0(Dec 21, 2015)

Owner
Lektor CMS
A new kind of content management system for Python.
Lektor CMS
Static site generator that supports Markdown and reST syntax. Powered by Python.

Pelican Pelican is a static site generator, written in Python. Write content in reStructuredText or Markdown using your editor of choice Includes a si

Pelican dev team 10.7k Nov 30, 2021
An extremely simple, pluggable static site generator.

Metalsmith An extremely simple, pluggable static site generator. In Metalsmith, all of the logic is handled by plugins. You simply chain them together

Segment 7.7k Nov 24, 2021
Static Site Server/Generator with built-in preprocessing

Harp zero-configuration web server with built in pre-processing What is Harp? Harp is a static web server that also serves Jade, Markdown, EJS, Less,

Brock Whitten 4.9k Nov 29, 2021
A simple static site generator for photoessays

Exposé A simple static site generator for photoessays Intro If you're into photography, you probably have folders of images and videos like this: Expo

Jack Qiao 4.2k Nov 30, 2021
A static website and blog generator

Nikola, a Static Site and Blog Generator In goes content, out comes a website, ready to deploy. Why Static Websites? Static websites are safer, use fe

Nikola, a static site generator 2.2k Nov 18, 2021
Java based open source static site/blog generator for developers & designers.

JBake JBake JBake is a Java based open source static site/blog generator for developers. Documentation Full documentation is available on jbake.org. C

JBake 957 Nov 30, 2021
🔥🔪 A blazing-fast static site generator using Laravel's Blade templating engine

Cleaver ?? A blazing-fast static site generator that uses Laravel's Blade templating engine and leverages JSON or Markdown files for super-extensible

Andrew Schmelyun 172 Nov 25, 2021
[READ-ONLY] An open source Content Application Platform based on Flow. A set of core Content Management features is resting within a larger context that allows you to build a perfectly customized experience for your users

The Neos package Note This repository is a read-only subsplit of a package that is part of the Neos project (learn more on www.neos.io). Neos is an op

Neos 97 Nov 25, 2021
Business class content management for Node.js (plugins, server cluster management, data-driven pages)

PencilBlue A full featured Node.js CMS and blogging platform (plugins, server cluster management, data-driven pages) First and foremost: If at any poi

PencilBlue, LLC. 1.6k Nov 17, 2021
Simple static file server with cli and webinterface. This is just a mirror repo

Surfer Surfer is a Simple static file server. It comes with a commandline tool to upload files from your local folders and a webinterface to manage fi

Cloudron 41 Oct 26, 2021
Simple static file server with cli and webinterface. This is just a mirror repo

Surfer Surfer is a Simple static file server. It comes with a commandline tool to upload files from your local folders and a webinterface to manage fi

Cloudron 41 Oct 26, 2021
Home of the Joomla! Content Management System

Joomla! CMS™ Build Status Drone-CI AppVeyor What is this? This is a Joomla! 3.x installation/upgrade package. Joomla's Official website. Joomla! 3.9 v

Joomla! 4k Dec 1, 2021
Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.

Orchard Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. You can try it for free on DotN

OrchardCMS 2.3k Nov 22, 2021
The TYPO3 Core - Enterprise Content Management System. Synchronized read-only mirror of http://git.typo3.org/Packages/TYPO3.CMS.git

TYPO3 CMS TYPO3 is an open source PHP based web content management system released under the GNU GPL. TYPO3 is copyright (c) 1999-2021 by Kasper Skaar

TYPO3 GitHub Department 806 Nov 28, 2021
Camaleon CMS is a dynamic and advanced content management system based on Ruby on Rails

CAMALEON CMS Website Documentation Demonstration About Camaleon CMS is a dynamic and advanced content management system based on Ruby on Rails that ad

Owen Peredo Diaz 1.2k Nov 28, 2021
A flexible, elegant, fast and easy-to-use content management system written in PHP.

Textpattern CMS A flexible, elegant, fast and easy-to-use content management system written in PHP. Textpattern is free and open source software. Syst

Textpattern CMS 640 Nov 26, 2021
Subrion CMS - open source php content management system.

Subrion CMS What is Subrion? Subrion is a Content Management System (CMS) which allows you to build websites for any purpose. Yes, from blog to corpor

Intelliants 267 Oct 15, 2021
A modern, ultra lightweight and rocket fast Content Management System

Redaxscript A modern, ultra lightweight and rocket fast Content Management System for SQLite, MSSQL, MySQL and PostgreSQL. Installation Clone the repo

redaxscript 246 Nov 10, 2021
ComfortableMexicanSofa is a powerful Ruby on Rails 5.2+ CMS (Content Management System) Engine

ComfortableMexicanSofa ComfortableMexicanSofa is a powerful Ruby on Rails 5.2+ CMS (Content Management System) Engine Features Simple drop-in integrat

Comfy Projects 2.7k Nov 17, 2021
Radiant is a no-fluff, open source content management system designed for small teams.

Welcome to Radiant Radiant is a no-fluff, open source content management system designed for small teams. It is similar to Textpattern or MovableType,

Radiant CMS dev team 1.7k Nov 19, 2021
PushType is a modern, open source content management system for Ruby on Rails.

PushType PushType is a modern content management system for Ruby on Rails. It takes advantage of powerful new features available in the latest version

PushType 295 Nov 12, 2021
A Django content management system focused on flexibility and user experience

Wagtail is an open source content management system built on Django, with a strong community and commercial support. It's focused on user experience,

Wagtail 11.3k Nov 30, 2021
wiki is a self-hosted well uh wiki engine or content management system

wiki wiki is a self-hosted well uh wiki engine or content management system that lets you create and share content in Markdown format. Source $ go get

James Mills 99 Jun 15, 2021
Metadata and content storage for Alfresco Content Services (Community and Enterprise)

This project has now been Archived The alfresco-core, alfresco-data-model, alfresco-repository and alfresco-remote-api projects have been archived wit

Alfresco Software 90 Sep 28, 2021
High performance file syncing and sharing, with also Markdown WYSIWYG editing, Wiki, file label and other knowledge management features.

Introduction Seafile is an open source cloud storage system with privacy protection and teamwork features. Collections of files are called libraries.

null 9.1k Nov 30, 2021
High performance file syncing and sharing, with also Markdown WYSIWYG editing, Wiki, file label and other knowledge management features.

Introduction Seafile is an open source cloud storage system with privacy protection and teamwork features. Collections of files are called libraries.

null 9.1k Nov 30, 2021
Add content management functionality to any site - plug & play / headless / api-first CMS

Cockpit Next Homepage: http://getcockpit.com Twitter: @getcockpit Support Forum: https://discourse.getcockpit.com Requirements PHP >= 7.3 PDO + SQLite

Agentejo 5.2k Nov 29, 2021
MODX Revolution - Content Management Framework

MODX Revolution MODX Revolution is the world’s fastest, most secure, flexible and scalable Open Source CMS. Content Management System and Application

MODX Content Management 1.3k Nov 28, 2021