正确导入模块,公开用于打包和开发的功能

时间:2019-02-17 20:51:53

标签: python python-3.x mocking pytest setuptools

目标

我正在尝试配置一个项目,以使其在开发过程中和打包后都能正常工作。我需要实现多个目标,但似乎无法单独处理它们,因此一个人会失败的。

  1. 能够在设置环境变量PYTHONPATH之后通过命令行运行测试
  2. 能够从IDE中运行/调试测试,可能会定义环境变量PYTHONPATH
  3. 在CI(Travis)期间运行测试
  4. 除了需要的功能外,不要暴露其他任何东西
  5. 公开一个函数
  6. 可作为命令行界面调用

上下文

这是我的项目结构。我喜欢这种方式,但我很乐意对其进行更改以满足上述要求。但我真的不希望混合使用测试和源,资源和代码。

.
├── LICENSE
├── README.md
├── mysql_tracer
│   ├── __init__.py
│   ├── __main__.py
│   ├── chest.py
│   ├── cursor_provider.py
│   ├── query.py
│   └── writer.py
├── requirements.txt
├── setup.py
└── tests
    ├── assets
    │   ├── sample-query-executed.csv
    │   ├── sample-query-executed.sql
    │   ├── sample-query.sql
    │   └── sample-template-query.sql
    └── python
        ├── __init__.py
        ├── conftest.py
        ├── test_query.py
        └── test_writer.py

4 directories, 18 files

发展

在开发过程中,我设置了1、2和3。我很难做到这一点,因为模块之间的导入,从测试的导入和模拟模块的工作似乎都不同。我使用以下方法管理了一个可行的解决方案:

  • 模块query.py使用import writer导入模块writer.py
  • 模块query.py使用from cursor_provider import CursorProvider从模块cursor_provider.py导入类CursorProvider
  • 模块test_query.py使用import query导入查询
  • 模块test_query.py的功能test_result模拟使用@mock.patch('query.CursorProvider')从模块query.py导入的模块CursorProvider
  • .travis.yml将测试定义为:
script:
- export PYTHONPATH=mysql_tracer
- pytest

最后一部分特别直观,因为我尝试的以前的设置将使终端运行语言环境测试而无需设置环境变量,因此Idea总是能够以某种方式工作。需要为Travis和本地终端进行设置的工作设置。

一个人可以搜索我的git历史记录,并发现在使其正常工作之前我必须尝试很多事情:

$ git log 1e5338dfab429d894a109a287f2a087c5d945a90..39c6e093e3bdb4470f374c4eb50d02ec52cb878a --pretty=format:"%h%x09%ad%x09%s"
39c6e09 Mon Feb 11 01:15:04 2019 +0100  travis, just do it please
544e540 Mon Feb 11 01:00:17 2019 +0100  mark it work locally... we'll see for CI later
a38caaa Mon Feb 11 00:10:50 2019 +0100  combine regexes with or
7a1eb88 Sun Feb 10 23:43:35 2019 +0100  travis, you're the last one, just f* works please
042f7c3 Sun Feb 10 23:08:14 2019 +0100  travis, mock, pytest, I changed everything, are you happy now ?
79e45c9 Sun Feb 10 22:54:35 2019 +0100  travis, get your shit together please
17eafaa Sun Feb 10 22:48:39 2019 +0100  another way to expose and import module to please both travis and mock
ea93558 Sun Feb 10 22:39:05 2019 +0100  test
4956d5a Sun Feb 10 21:34:31 2019 +0100  another way to expose Query...
98ff216 Sun Feb 10 21:22:33 2019 +0100  import differently
2426a6d Sun Feb 10 21:20:30 2019 +0100  expose Query
851ea43 Sun Feb 10 21:17:09 2019 +0100  setup.py

包装

但是现在开发即将结束,我已经设置了软件包配置以支持5和6。不幸的是,我没有正确设置4,所以我破坏了1、2和3。

我必须更改模块之间的导入,因为否则在本地安装或从pypi安装后使用我的软件包将无法正常工作。

  • 我会做import writer而不是做from . import writer
  • 我会做from cursor_provider import CursorProvider(注意模块名称前的点),而不是做from .cursor_provider import CursorProvider

这使我的cli界面正常工作。之后,我可以使用

$ mysql_tracer -h
... skipped output ...
$ mysql_tracer --host 127.0.0.1 --user aho --database company --destination /home/aho/Downloads /home/aho/sources/sql-test-tools/people.sql

在这一点上,导入模块mysql_tracer可以正常工作,但是什么都不暴露。但是,将以下行添加到mysql_tracer/__init__.py文件中将显示查询类:

from .query import Query

但是在包mysql_tracer(列表结尾)中定义的所有模块也是如此:

>>> import mysql_tracer
>>> dir(mysql_tracer)
['Query', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'chest', 'cursor_provider', 'query', 'writer']

虽然它不会打扰太多,但却是不希望的。我仅表示属性查询可用。 胸部,cursor_provider,查询和作家应该被隐藏。请注意,在我尝试公开Query类之前,它们不可用。

但是现在,使软件包功能起作用的import语句使测试失败:

    from . import writer
E   ImportError: attempted relative import with no known parent package

那么,如何在恢复开发要求(1,2和3)的同时保持功能(5和6)正常工作?也许还有功能4?

我希望我提供了必要且充分的信息,但是如果您需要更多信息,请访问my projectpackageCI page或发表评论并要求澄清。

0 个答案:

没有答案