Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • w/shared/mwclient
1 result
Show changes
Commits on Source (65)
Showing
with 202 additions and 82 deletions
[aliases]
test = pytest
[flake8]
max-line-length = 90
ignore =
ignore =
# Line break before binary operator
W503
---
name: Run integration tests
on: ["push", "pull_request"]
jobs:
build:
runs-on: "ubuntu-latest"
strategy:
max-parallel: 4
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5.4.0
with:
python-version: '3.13'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
- name: Install podman
run: sudo apt-get -y install podman
- name: Integration test with tox
run: tox -e integration
......@@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.4.0
with:
python-version: "3.x"
......
......@@ -18,9 +18,12 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
- "3.13.0-alpha - 3.13"
- "3.13"
- "3.14.0-alpha - 3.14"
include:
- os: "ubuntu-latest"
- os: "ubuntu-22.04"
python-version: "3.7"
- os: "ubuntu-20.04"
python-version: "3.6"
......@@ -29,7 +32,7 @@ jobs:
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.4.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
......@@ -39,8 +42,8 @@ jobs:
- name: Test with tox
run: tox
- name: Produce coverage.lcov for coveralls
if: matrix.python-version == '3.11'
if: matrix.python-version == '3.13'
run: coverage lcov
- name: Coveralls
if: matrix.python-version == '3.11'
if: matrix.python-version == '3.13'
uses: coverallsapp/github-action@v2
......@@ -8,5 +8,6 @@ dist
.eggs
.tox
.idea/*
.venv/
.coverage
coverage.lcov
version: 2
build:
os: ubuntu-22.04
os: ubuntu-24.04
tools:
python: "3.11"
python: "3.12"
sphinx:
configuration: docs/source/conf.py
......@@ -12,4 +12,5 @@ python:
install:
- method: pip
path: .
- requirements: docs/requirements.txt
extra_requirements:
- docs
......@@ -30,9 +30,14 @@ Not long after the git transition, the repository was moved to an organization
([#12, comment](https://github.com/mwclient/mwclient/issues/12#issuecomment-20447515)),
and Dan became the main force behind the 2014 release of version 0.7.0
(the first after a 3-year hiatus).
Since then, he has been the lead maintainer of the project,
From then until the 0.10.1 release in 2020, he was the lead maintainer of the project,
which has attracted contributions from
[several other people](../../graphs/contributors).
From 2023, the project is maintained by
Marc Trölitzsch ([@marcfrederick](https://github.com/marcfrederick)),
Adam Williamson ([@adamwill](https://github.com/adamwill)),
and Megan Cutrofello ([@RheingoldRiver](https://github.com/RheingoldRiver)).
For more details on the technical history of the project,
see the [CHANGELOG.md](CHANGELOG.md) document.
include CHANGELOG.md
include CONTRIBUTING.md
include CREDITS.md
include README.md
include LICENSE.md
# prospector config - https://github.com/landscapeio/prospector
include .landscape.yaml
include .editorconfig
include tox.ini
graft docs
graft examples
......@@ -23,13 +23,13 @@
mwclient is a lightweight Python client library to the
[MediaWiki API](https://mediawiki.org/wiki/API)
which provides access to most API functionality.
It works with Python 3.5 and above,
and supports MediaWiki 1.16 and above.
It works with Python 3.6 and above,
and supports MediaWiki 1.21 and above.
For functions not available in the current MediaWiki,
a `MediaWikiVersionError` is raised.
The current stable
[version 0.10.1](https://github.com/mwclient/mwclient/archive/v0.10.1.zip)
[version 0.11.0](https://github.com/mwclient/mwclient/archive/v0.11.0.zip)
is [available through PyPI](https://pypi.python.org/pypi/mwclient):
```
......@@ -63,6 +63,15 @@ There is also some documentation on the [GitHub wiki](https://github.com/mwclien
that hasn't been ported yet.
If you want to help, you're welcome!
## License
mwclient is licensed under the MIT license. See the [LICENSE.md](LICENSE.md)
file for details.
## Versioning
This project adheres to [Semantic Versioning](http://semver.org/).
## Contributing
Patches are welcome! See [this page](https://mwclient.readthedocs.io/en/latest/development/)
......
sphinx==7.2.5
sphinx_rtd_theme==1.3.0
# -*- coding: utf-8 -*-
#
# mwclient documentation build configuration file, created by
# sphinx-quickstart on Sat Sep 27 11:19:56 2014.
......@@ -55,7 +54,7 @@ master_doc = 'index'
# General information about the project.
project = 'mwclient'
copyright = '{0}, Bryan Tong Minh'.format(datetime.datetime.now().year)
copyright = f'{datetime.datetime.now().year}, Bryan Tong Minh'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
......@@ -275,3 +274,6 @@ texinfo_documents = [
intersphinx_mapping = {
'requests': ('http://requests.readthedocs.org/en/latest/', None)
}
# Controls the display of typehints in the autodoc output.
autodoc_typehints = 'description'
......@@ -38,54 +38,122 @@ Create a new branch for your changes:
Test suite
----------
mwclient ships with a test suite based on `pytest <https://pytest.org>`_.
While it's far from complete, it can sometimes alert you if you break things.
mwclient ships with a test suite based on `pytest <https://pytest.org>`_. While
it's far from complete, it can sometimes alert you if you break things.
The easiest way to run the tests is:
To run the test suite, you can use `tox <https://tox.testrun.org/>`_. Tox will
create a virtual environment for each Python version you want to test with,
install the dependencies, and run the tests.
.. code:: bash
$ python setup.py test
$ pip install tox
$ tox
This will make an in-place build and download test dependencies locally if needed.
Tests will run faster, however, if you do an
`editable install <https://pip.readthedocs.org/en/latest/reference/pip_install.html#editable-installs>`_
and run pytest directly:
If you want to run the tests for a single Python version, you can do so by
specifying the Python version, e.g. to run the tests for Python 3.9:
.. code:: bash
$ pip install pytest pytest-cov flake8 responses mock
$ pip install -e .
$ tox -e py39
Alternatively, you can run the tests directly with pytest:
.. code:: bash
$ pip install -e '.[testing]'
$ py.test
If you want to test with different Python versions in isolated virtualenvs,
you can use `Tox <https://tox.testrun.org/>`_. A `tox.ini` file is included.
There is a container-based integration test suite which is not run by default
as it requires docker or podman, is a little slow, and needs to do ~3G of network
transfer when first run (to download the mediawiki container images). It is
run as part of CI. To run it locally, make sure you have docker or podman
installed, then with tox, do:
.. code:: bash
$ pip install tox
$ tox
$ tox -e integration
Or with pytest, do:
.. code:: bash
$ py.test test/integration.py
If you would like to expand the test suite by adding more tests, please go ahead!
Updating/expanding the documentation
------------------------------------
Documentation consists of both a manually compiled user guide
(under ``docs/user``) and a reference guide generated from the docstrings,
using Sphinx autodoc with the napoleon extension.
Documentation is built automatically on `ReadTheDocs <https://mwclient.readthedocs.io/>`_
after each commit.
To build the documentation locally for testing:
The documentation for this project consists of two main parts:
.. code:: bash
1. A manually compiled user guide (located in ``docs/user/``).
2. A reference guide automatically generated from docstrings using Sphinx
autodoc with the napoleon extension.
Builds
^^^^^^
Automatic Builds
""""""""""""""""
Documentation is automatically built on `ReadTheDocs <https://mwclient.readthedocs.io/>`_
after each commit. The configuration for this can be found in ``.readthedocs.yaml``.
$ pip install Sphinx sphinx-rtd-theme
$ cd docs
$ make html
Local Builds
""""""""""""
To build and test the documentation on your local machine:
1. Install the documentation dependencies:
.. code:: bash
$ pip install -e '.[docs]'
2. Build the documentation:
.. code:: bash
$ cd docs
$ make html
The generated HTML documentation will be available in ``docs/build/html/``.
Open ``docs/build/html/index.html`` in your browser to view it.
If you make
changes to the documentation, you can rebuild it by running ``make html``
again and then refreshing the page in your browser. To rebuild after making
changes, run ``make html`` again and refresh your browser.
Writing Docstrings
^^^^^^^^^^^^^^^^^^
When writing docstrings, try to adhere to the
`Google style <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_.
For example:
.. code:: python
def my_function(foo: str) -> str:
"""This is a function that does something.
Args:
foo: A string to do something with.
Returns:
A string with the result.
"""
You can also use `Sphinx-specific directives <https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html>`_
in your docstrings to provide additional information. Some useful directives
include:
- ``.. warning ::``: Highlight potential issues.
- ``.. note ::``: Provide additional information.
- ``.. seealso ::``: Link to related documentation.
- ``.. deprecated ::``: Mark a function as deprecated.
Making a pull request
---------------------
......@@ -108,7 +176,8 @@ When it is ready, push your branch to your remote:
$ git push -u fork my-branch
Then you can open a pull request on GitHub. You should see a URL to do this
when you push your branch.
when you push your branch. Tests will be automatically run on your pull
request via GitHub Actions.
Making a release
----------------
......
......@@ -6,9 +6,9 @@ mwclient: lightweight MediaWiki client
:align: right
:width: 30%
Mwclient is a :ref:`MIT licensed <license>` client library to the `MediaWiki API`_
that should work well with both Wikimedia wikis and other wikis running
MediaWiki 1.16 or above. It works with Python 2.7 and 3.3+.
Mwclient is an :ref:`MIT licensed <license>` client library for the `MediaWiki API`_
that works well with both Wikimedia wikis and other wikis running
MediaWiki 1.21 or above. It is compatible with Python 3.6 and above.
.. _install:
......@@ -81,7 +81,23 @@ Looking for information on contributing to mwclient development?
MIT License
-----------
.. include:: ../../LICENSE.md
This project is licensed under the MIT License. The full text of the license
is reproduced below:
.. literalinclude:: ../../LICENSE.md
:language: text
Versioning
----------
Mwclient uses `Semantic Versioning 2.0.0 <http://semver.org>`_. Versions are
numbered ``MAJOR.MINOR.PATCH``. The version will be incremented based on the
following:
* `MAJOR` version is incremented when backwards incompatible changes are made.
* `MINOR` version is incremented when functionality is added in a backwards
compatible manner.
* `PATCH` version is incremented when backwards compatible bug fixes are made.
Indices and tables
------------------
......
.. _errors:
:class:`InsufficientPermission`
:mod:`Errors <mwclient.errors>`
-------------------------------
.. autoclass:: mwclient.errors.InsufficientPermission
.. automodule:: mwclient.errors
:members:
:undoc-members:
:show-inheritance:
......@@ -74,7 +74,7 @@ Using a proxy
-------------
If you need to use a proxy, you can configure the :class:`requests.Session`
using the `reqs` parameter of the :class:`~mwclient.client.Site`.
using the `connection_options` parameter of the :class:`~mwclient.client.Site`.
.. code-block:: python
......@@ -84,7 +84,7 @@ using the `reqs` parameter of the :class:`~mwclient.client.Site`.
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
site = mwclient.Site('en.wikipedia.org', reqs={"proxy": proxies})
site = mwclient.Site('en.wikipedia.org', connection_options={"proxy": proxies})
Errors and warnings
-------------------
......
......@@ -13,7 +13,7 @@ Some notable exceptions:
* ``usercontribs`` is ``usercontributions``
* First parameters of ``search`` and ``usercontributions`` are ``search`` and ``user``, respectively
Properties and generators are implemented as Python generators. Their limit parameter is only an indication of the number of items in one chunk. It is not the total limit. Doing ``list(generator(limit = limit))`` will return ALL items of generator, and not be limited by the limit value. Use ``list(generator(max_items = max_items))`` to limit the amount of items returned. Default chunk size is generally the maximum chunk size.
Properties and generators are implemented as Python generators which yield one item per iteration. Their deprecated ``limit`` parameter is only an indication of the number of items retrieved from the API per request. It is not the total limit. Doing ``list(generator(limit = 50))`` will return ALL items, not 50, but it will query the API in chunks of 50 items at a time (so after yielding one item from the generator, the next 49 will be "free", then the next will trigger a new API call). The replacement ``api_chunk_size`` parameter does the same thing, but is more clearly named. If both ``limit`` and ``api_chunk_size`` are specified, ``limit`` will be ignored. The ``max_items`` parameter sets a total limit on the number of items which will be yielded. Use ``list(generator(max_items = 50))`` to limit the amount of items returned to 50. Higher level functions that have a ``limit`` parameter also now have ``api_chunk_size`` and ``max_items`` parameters that should be preferred. Default API chunk size is generally the maximum chunk size (500 for most wikis).
Page objects
------------
......
......@@ -64,7 +64,7 @@ is handled under the hood so you don't have to worry about it.
>>> from itertools import islice
>>> for revision in islice(page.revisions(), 5):
... dt = datetime.fromtimestamp(mktime(revision['timestamp']))
... print '{}'.format(dt.strftime('%F %T'))
... print(dt.strftime('%F %T'))
Categories
----------
......
......@@ -25,13 +25,12 @@ site = mwclient.ex.ConfiguredSite(sys.argv[1])
site.compress = False
print('Running configured site', sys.argv[1])
print('Site has writeapi:', getattr(site, 'writeapi', False))
page = site.Pages[prefix + '/text1']
page = site.Pages[f'{prefix}/text1']
print('Editing page1')
text1 = u"""== [[Test page]] ==
text1 = """== [[Test page]] ==
This is a [[test]] page generated by [http://mwclient.sourceforge.org/ mwclient].
This test is done using the [[w:mw:API]]."""
comment1 = 'Test page1'
......@@ -45,22 +44,23 @@ print('Links:', list(page.links(generator=False)))
print('External links:', list(page.extlinks()))
print('Uploading image')
site.upload(open('test-image.png', 'rb'), prefix + '-test-image.png', 'desc', ignore=True)
with open('test-image.png', 'rb', encoding='utf-8') as f:
site.upload(f, f'{prefix}-test-image.png', 'desc', ignore=True)
print('Uploading image for the second time')
site.upload(open('test-image.png', 'rb'), prefix + '-test-image.png', 'desc', ignore=True)
image = site.Images[prefix + '-test-image.png']
with open('test-image.png', 'rb', encoding='utf-8') as f:
site.upload(f, f'{prefix}-test-image.png', 'desc', ignore=True)
image = site.Images[f'{prefix}-test-image.png']
print('Imageinfo:', image.imageinfo)
history = list(image.imagehistory())
print('History:', history)
if site.writeapi:
print('Deleting old version')
archivename = history[1]['archivename']
image.delete('Testing history deletion', oldimage=archivename)
print('History:', list(image.imagehistory()))
print('Deleting old version')
archivename = history[1]['archivename']
image.delete('Testing history deletion', oldimage=archivename)
print('History:', list(image.imagehistory()))
text = page.text()
text += '\n[[Image:%s-test-image.png]]' % prefix
text += f'\n[[Image:{prefix}-test-image.png]]'
page.edit(text, 'Adding image')
print('Images:', list(page.images(generator=False)))
print('Cleaning up')
......
from io import StringIO
from io import BytesIO
import sys
import os
import pprint
......@@ -24,7 +24,7 @@ site.login(sys.argv[1], sys.argv[2])
name = ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for i in range(8)) + '.png'
print('Using http://%s%sindex.php?title=File:' % (host, path) + name)
print(f'Using http://{host}{path}index.php?title=File:{name}')
print('Regular upload test')
res = site.upload(open('test-image.png', 'rb'), name, 'Regular upload test', ignore=True)
......@@ -48,4 +48,4 @@ assert 'duplicate' in res['warnings']
assert 'exists' in res['warnings']
print('Uploading empty file; error expected')
res = site.upload(StringIO(), name, 'Empty upload test')
res = site.upload(BytesIO(), name, 'Empty upload test')
......@@ -24,7 +24,7 @@
"""
from mwclient.errors import * # noqa: F401, F403
from mwclient.client import Site, __version__ # noqa: F401
from mwclient.client import Site as Site, __version__ as __version__ # noqa: F401
import logging
import warnings
......