贡献

这个项目是一个社区的努力,欢迎每个人都参与进来。我们跟随 Python Software Foundation Code of Conduct 我们做的每件事。

该项目位于https://github.com/matplotlib/matplotlib上。

提交错误报告

如果在代码或文档中发现错误,请毫不犹豫地向 Bug Tracker . 也欢迎您发布功能请求或拉请求。

如果您报告错误,请尽最大努力包括以下内容:

  1. 这个bug的简短的顶级摘要。在大多数情况下,这应该是1-2句话。

  2. 一个简短的、自包含的代码片段来重现这个bug,理想情况下允许一个简单的复制和粘贴来重现。请尽最大努力将代码段减少到所需的最小值。

  3. 代码段的实际结果。

  4. 代码段的预期结果。

  5. 正在使用的matplotlib版本、python版本和平台。您可以使用以下命令获取版本:

    >>> import matplotlib
    >>> matplotlib.__version__
    '1.5.3'
    >>> import platform
    >>> platform.python_version()
    '2.7.12'
    

我们已经预加载了“问题创建”页面,其中包含一个可用于组织此信息的标记模板。

感谢您帮助保持错误报告的完整性、针对性和描述性。

检索和安装最新版本的代码

在开发matplotlib时,源必须下载、构建并安装到您机器上的本地环境中。

我们使用 Git 用于版本控制和 GitHub 用于托管我们的主存储库。

您可以使用命令签出最新的源(请参见 建立你的复刻 有关详细信息)::

git clone https://github.com/matplotlib/matplotlib.git

导航到 matplotlib 目录。如果您有适当的权限,可以使用 git@ 而不是 https:// 它通过ssh协议工作,如果使用2因素身份验证,则使用起来可能更容易。

在开发人员模式下安装Matplotlib

强烈建议建立一个干净的 virtual environment . 不要在预先存在的环境中使用!

可以使用以下设置新环境:

python3 -mvenv /path/to/devel/env

并通过以下方式之一激活:

source /path/to/devel/env/bin/activate  # Linux/macOS
/path/to/devel/env/Scripts/activate.bat  # Windows cmd.exe
/path/to/devel/env/Scripts/Activate.ps1  # Windows PowerShell

无论何时计划使用Matplotlib,请记住激活shell中的开发环境!

要安装Matplotlib(并编译C扩展),请从顶层目录运行以下命令:

python -mpip install -ve .

这将在“可编辑/开发模式”下安装matplotlib,即构建所有内容并将正确的链接条目放置在安装目录中,以便python能够从源目录导入matplotlib。因此,对 *.py 文件将在下次导入库时反映出来。如果更改C扩展源(如果更改分支可能会发生这种情况),则需要运行::

python setup.py build_ext --inplace

或重新运行 python -mpip install -ve . .

然后可以运行测试,以检查工作环境是否正确设置:

python -mpytest

注解

测试的附加依赖项pytest (3.6版或更高版本), Ghostscript, Inkscape

贡献代码

如何贡献

有助于Matplotlib的首选方法是 main repository 在Github上,然后提交“拉请求”(pr)。

使用Github生成prs到matplotlib的最佳实践记录在 开发工作流 部分。

简要概述如下:

  1. Create an account 在Github上,如果您还没有。

  2. project repository :单击页面顶部附近的“fork”按钮。这将在GitHub服务器上的帐户下创建代码的副本。

  3. 将此副本复制到本地磁盘:

    $ git clone https://github.com/YourLogin/matplotlib.git
    
  4. 创建一个分支以保存更改::

    $ git checkout -b my-feature origin/master
    

    开始改变。从来没有工作在 master 分支!

  5. 在您的计算机上处理这个副本,使用git进行版本控制。完成编辑后,例如, lib/matplotlib/collections.py DO::

    $ git add lib/matplotlib/collections.py
    $ git commit
    

    要在Git中记录您的更改,请使用以下命令将其推送到GitHub:

    $ git push -u origin my-feature
    

最后,转到Matplotlibrepo分支的网页,单击“拉请求”将更改发送给维护人员以供审阅。您可能需要考虑向邮件列表发送电子邮件以获得更大的可见性。

参与请求

建议在提交请求前检查您的贡献是否符合以下规则:

  • 如果您的请求解决了某个问题,请使用标题描述该问题,并在请求描述中提及问题编号,以确保创建到原始问题的链接。

  • 所有公共方法都应具有信息性文档字符串,并在适当时使用示例。使用 numpy docstring standard .

  • 格式应遵循的建议 PEP8 . 您应该考虑在编辑器中安装/启用自动PEP8签入。测试套件的一部分是检查PEP8的遵从性,如果从一开始代码基本上是符合PEP8的,事情就会变得更顺利。

  • 每个高级绘图函数都应该有一个简单的示例 Example 文档字符串的节。这应该尽可能简单地演示该方法。更复杂的例子应该放在 examples 树。

  • 应测试更改(新功能和错误修复)。见 开发人员测试提示 了解更多详细信息。

  • 使用标准scipy约定导入以下模块:

    import numpy as np
    import numpy.ma as ma
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    import matplotlib.cbook as cbook
    import matplotlib.patches as mpatches
    

    通常,Matplotlib模块应该 not 进口 rcParams 使用 from matplotlib import rcParams ,而是作为 mpl.rcParams . 这是因为有些模块很早就被导入了 rcParams 构造了单态子。

  • 如果您的更改是主要的新功能,请在 What's new 在中添加新文件的节 doc/users/next_whats_new (见 doc/users/next_whats_new/README.rst 更多信息)。

  • 如果您以向后不兼容的方式更改API,请将其记录在 doc/api/api_changes ,通过添加到相关文件(请参见 doc/api/api_changes.rst 更多信息)

  • 有关更多信息,请参见下文 关键字参数处理 ,如果适用于您的拉车请求。

此外,还可以使用以下工具检查常见的编程错误:

  • 代码具有良好的UnitTest覆盖率(至少70%,更好100%),请检查:

    python -mpip install coverage
    python -mpytest --cov=matplotlib --showlocals -v
    
  • 没有Pyflakes警告,请检查:

    python -mpip install pyflakes
    pyflakes path/to/module.py
    

注解

Matplotlib代码库的当前状态不符合所有这些指导原则,但是我们希望对所有新贡献实施这些约束将使整个代码库质量朝着正确的方向发展。

新参与者的问题

新参与者在查找问题时应查找以下标记。我们强烈建议新的撰稿人处理标记为 good first issue 由于这些问题很容易记录,不需要理解matplotlib的不同子模块。这有助于贡献者熟悉贡献工作流,使核心开发人员熟悉贡献者;此外,我们经常低估了解决问题的容易程度!

提供文件

代码不是对Matplotlib做出贡献的唯一方法。例如,文档也是项目的一个非常重要的部分,并且常常没有得到应有的重视。如果您发现文档中有错别字,或者已经进行了改进,请立即向邮件列表发送电子邮件或提交GitHub请求。请参考提拉指南 如何贡献 .

完整的文档可以在 doc/tutorials/examples/ 目录。

参见

其他贡献方式

它也有助于我们如果你传播这个词:从你的博客和文章或链接到它从你的网站!如果Matplotlib为一个项目提供了一份科学出版物,请按照 引用 Matplotlib 指南。

编码指南

API更改

对公共API的更改必须遵循标准的弃用过程,以防止使用Matplotlib的代码意外中断。

  • 必须通过最近的 doc/api/api_changes_X.Y
  • 反对的目标是下一个点版本(即3.x.0)。
  • 不推荐使用的API应尽可能在弃用期间保持完整的功能。在不可能做到的情况下,弃用决不能使给定的代码执行与以前不同的操作;至少应该引发异常。
  • 如果可能的话,使用不推荐的API应该发出 MatplotlibDeprecationWarning . 有许多帮助工具可用于此目的:
    • 使用 cbook.warn_deprecated() 对于一般的弃用警告。
    • 使用装饰器 @cbook.deprecated 弃用类、函数、方法或属性。
    • 要对函数签名的更改发出警告,请使用decorators @cbook._delete_parameter@cbook._rename_parameter@cbook._make_keyword_only .
  • 不推荐使用的API可能会在其被弃用后被删除。

添加新API

每个没有显式标记为private(即以下划线开头)的新函数、参数和属性都成为Matplotlib公共API的一部分。如上所述,更改现有的API非常麻烦。因此,添加新API时要特别小心:

  • 通过在助手函数和内部属性前面加下划线,将它们标记为私有。
  • 仔细考虑函数和变量的好名字。
  • 尝试从matplotlibapi的现有部分采用模式和命名约定。
  • 考虑尽可能多地使用参数关键字。另请参见 `API Evolution the Right Way -- Add Parameters Compatibly`_ _.

新模块和文件:安装

  • 如果添加了新文件或目录,或重新组织了现有文件或目录,请确保新文件包含在中的匹配模式中。 MANIFEST.in 和/或 package_data 在里面 setup.py .

C/C++扩展

  • 扩展可以用C或C++编写。
  • 代码风格应该符合PEP7(理解PEP7不处理C++,但它的大多数警告仍然适用)。
  • Python/C接口代码应该与核心C/C++代码保持分开。接口代码应命名为 FOO_wrap.cppFOO_wrapper.cpp .
  • 头文件文档(aka docstrings)应为numpydoc格式。我们不打算为这些docstring使用自动化工具,而且numpydoc格式在科学的python社区中是很好理解的。

关键字参数处理

Matplotlib广泛使用 **kwargs 用于从一个函数到另一个函数的传递自定义。一个典型的例子是 matplotlib.pyplot.text() . pylab文本函数的定义是一个简单的传递到 matplotlib.axes.Axes.text() ::

# in pylab.py
def text(*args, **kwargs):
    ret =  gca().text(*args, **kwargs)
    draw_if_interactive()
    return ret

text() 在简化形式中,它看起来像这样,即,它只通过所有 argskwargsmatplotlib.text.Text.__init__() ::

# in axes/_axes.py
def text(self, x, y, s, fontdict=None, withdash=False, **kwargs):
    t = Text(x=x, y=y, text=s, **kwargs)

__init__() (再一次自由地举例说明)把它们传给 matplotlib.artist.Artist.update() 方法:

# in text.py
def __init__(self, x=0, y=0, text='', **kwargs):
    Artist.__init__(self)
    self.update(kwargs)

update 这项工作是否在寻找类似 set_property 如果 property 是关键字参数。也就是说,没有人查看关键字,它们只是通过API传递给Artist构造函数,后者查找适当命名的方法并用值调用它们。

一般来说,使用 **kwargs 应该为pass-through关键字参数保留,如上面的示例所示。如果所有关键字参数都要在函数中使用而不是传递,请在函数定义中使用键/值关键字参数,而不是 **kwargs 成语。

在某些情况下,您可能需要使用本地函数中的一些键,并让其他键通过。而不是弹出参数来使用 **kwargs ,将它们指定为本地函数的仅关键字参数。这使得我们可以一目了然地看到函数中将使用哪些参数。例如,在 plot()scalexscaley 是本地参数,其余的作为 Line2D() 关键字参数::

# in axes/_axes.py
def plot(self, *args, scalex=True, scaley=True, **kwargs):
    lines = []
    for line in self._get_lines(*args, **kwargs):
        self.add_line(line)
        lines.append(line)

使用日志记录调试消息

matplotlib使用标准python logging 用于写入详细警告、信息和调试消息的库。请使用它!在你写的那些地方 print() 要进行调试的语句,请尝试使用 log.debug() 相反!

包括 logging 在您的模块中,在模块顶部,您需要 import logging . 然后在代码中调用如下:

_log = logging.getLogger(__name__)  # right after the imports

# code
# more code
_log.info('Here is some information')
_log.debug('Here is some more detailed information')

将登录到名为 matplotlib.yourmodulename .

如果Matplotlib的最终用户设置了 logging 显示在比 logging.WARNING 在他们的代码中使用Matplotlib提供的助手:

plt.set_loglevel("debug")

或手动使用:

import logging
logging.basicConfig(level=logging.DEBUG)
import matplotlib.pyplot as plt

然后他们会收到如下信息:

DEBUG:matplotlib.backends:backend MacOSX version unknown
DEBUG:matplotlib.yourmodulename:Here is some information
DEBUG:matplotlib.yourmodulename:Here is some more detailed information

要使用哪个日志级别?

有五个级别可以发出消息。

  • logging.criticallogging.error 但这并不仅仅是为了解释器的结束而使用的。
  • logging.warningcbook._warn_external 用于警告用户,请参见下文。
  • logging.info 用户可能想知道程序是否有异常行为。默认情况下不显示它们。例如,如果一个对象没有被绘制,因为它的位置是 NaN ,这通常可以忽略,但神秘用户可以调用 logging.basicConfig(level=logging.INFO) 并得到一条错误消息,说明原因。
  • logging.debug 最不可能显示,因此可能最冗长。”“预期的”代码路径(例如,报告布局或呈现的正常中间步骤)只应记录在该级别。

默认情况下, logging 以高于的级别显示所有日志消息 logging.WARNINGsys.stderr .

这个 logging tutorial 这说明 logging.warningcbook._warn_external (使用 warnings.warn )是这样吗 cbook._warn_external 应该用于用户必须更改以停止警告的内容(通常在源代码中),而 logging.warning 可以更持久。此外,请注意 cbook._warn_external 默认情况下只发出给定的警告 once 对于每行用户代码 logging.warning 每次调用时都会显示消息。

默认情况下, warnings.warn 显示具有 warn 打电话。这通常并不比警告消息本身更具信息性。因此,Matplotlib使用 cbook._warn_external 其中使用 warnings.warn ,但会进入堆栈并显示Matplotlib之外的第一行代码。例如,对于模块:

# in my_matplotlib_module.py
import warnings

def set_range(bottom, top):
    if bottom == top:
        warnings.warn('Attempting to set identical bottom==top')

运行脚本:

from matplotlib import my_matplotlib_module
my_matplotlib_module.set_range(0, 0)  #set range

将显示:

UserWarning: Attempting to set identical bottom==top
warnings.warn('Attempting to set identical bottom==top')

修改要使用的模块 cbook._warn_external ::

from matplotlib import cbook

def set_range(bottom, top):
    if bottom == top:
        cbook._warn_external('Attempting to set identical bottom==top')

运行相同的脚本将显示:

UserWarning: Attempting to set identical bottom==top
my_matplotlib_module.set_range(0, 0)  #set range

写例子

我们有上百个例子在 matplotlib/examples ,当网站构建为显示在 examples 网站的部分。

示例使用的任何示例数据都应保持较小并与Matplotlib一起分布在 lib/matplotlib/mpl-data/sample_data/ 目录。然后,在示例代码中,可以使用以下命令将其加载到文件句柄中:

import matplotlib.cbook as cbook
fh = cbook.get_sample_data('mydata.dat')