Path: csiph.com!usenet.pasdenom.info!news.etla.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed2.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'url:pipermail': 0.05; 'dynamically': 0.07; 'assuming': 0.09; 'chairs': 0.09; 'executable': 0.09; 'function,': 0.09; 'setup.py': 0.09; 'structure,': 0.09; 'unittest': 0.09; 'valueerror:': 0.09; 'runs': 0.10; 'cc:addr:python-list': 0.11; 'python': 0.11; '"from': 0.16; '(say': 0.16; '24,': 0.16; '5:30': 0.16; '__init__.py': 0.16; 'above?': 0.16; 'attempted': 0.16; 'be:': 0.16; 'broken.': 0.16; 'expect,': 0.16; 'imports': 0.16; 'modules.': 0.16; 'nose': 0.16; 'pytest,': 0.16; 'script?': 0.16; 'subject: \n ': 0.16; 'url:html)': 0.16; 'exception': 0.16; 'wrote:': 0.18; 'skip:f 30': 0.19; 'work,': 0.20; 'seems': 0.21; 'command': 0.22; 'import': 0.22; 'separate': 0.22; 'tests': 0.22; 'cc:addr:python.org': 0.22; 'install': 0.23; 'either.': 0.24; 'package.': 0.24; 'guys': 0.24; 'looks': 0.24; '(or': 0.24; 'cc:2**0': 0.24; 'script': 0.25; 'right.': 0.26; 'this:': 0.26; 'pass': 0.26; 'somewhere': 0.26; 'header:In-Reply-To:1': 0.27; 'testing': 0.29; 'relative': 0.30; 'message-id:@mail.gmail.com': 0.30; "i'm": 0.30; 'code': 0.31; 'getting': 0.31; 'apparently': 0.31; 'loading': 0.31; 'them?': 0.31; "they'll": 0.31; 'yes.': 0.31; 'probably': 0.32; 'run': 0.32; 'url:python': 0.33; 'running': 0.33; '(e.g.': 0.33; 'plain': 0.33; 'third': 0.33; 'table': 0.34; 'skip:_ 10': 0.34; 'there,': 0.34; 'problem': 0.35; 'subject:with': 0.35; 'advice': 0.35; 'something': 0.35; 'no,': 0.35; 'test': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'really': 0.36; 'accessible': 0.36; 'installing': 0.36; 'interface,': 0.36; 'subject:?': 0.36; 'url:org': 0.36; 'should': 0.36; 'example,': 0.37; 'unit': 0.37; 'nov': 0.38; 'url:library': 0.38; 'work?': 0.38; 'files': 0.38; 'pm,': 0.38; 'anything': 0.39; 'skip:. 10': 0.39; 'structure': 0.39; 'either': 0.39; 'url:mail': 0.40; 'how': 0.40; 'skip:u 10': 0.60; 'such': 0.63; 'more': 0.64; 'different': 0.65; 'to:addr:gmail.com': 0.65; 'within': 0.65; 'license': 0.66; 'discover': 0.82; 'everywhere.': 0.84; "it'd": 0.84; 'victor': 0.84; 'reasons,': 0.91; '2013': 0.98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=pf0uJm5WU9/HEtQJRTNVfynQDBud1X3Wp+8Q8fSt1a8=; b=egNSAzo1OYqRO1aNI30g8yMbobQi6gevGG3wAoQN+esRqKHfa3vVdmdLRZMNeh0rEJ 0O+E5BFDwk1v+alUX8665OkOcDS31IFBComuOBcdajuSybBaDOueNU80FRIUg487Gqgf 6QbiEEjjoUwGwtXKf/ELa1s+r9I4jbgk3z6UvpjlRKKb5QGOY5ZurBxFaxMZfWWbpmkc UPKYnG6pjYfL/JP2hno9y7oI4B1/gphl5zGii11VltDiON3n90SsSJy2RqlwuhwRB8sw xGgCOVIxCqV9OhAQycyIjiDNHl2zUEsey+/mu6J06aYhtj9keNZKg+gP0kqIVBSKnNru W7ow== X-Received: by 10.49.72.193 with SMTP id f1mr43217963qev.58.1385359297186; Sun, 24 Nov 2013 22:01:37 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <08fbd202-ebdf-4a41-a493-bc3b76a6c227@googlegroups.com> References: <08fbd202-ebdf-4a41-a493-bc3b76a6c227@googlegroups.com> From: Devin Jeanpierre Date: Sun, 24 Nov 2013 22:00:56 -0800 Subject: Re: Understanding relative imports in package - and running pytest with relative imports? To: Victor Hooi Content-Type: text/plain; charset=UTF-8 Cc: "comp.lang.python" X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 93 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1385359300 news.xs4all.nl 16005 [2001:888:2000:d::a6]:36020 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:60399 On Sun, Nov 24, 2013 at 5:30 PM, Victor Hooi wrote: > The advice seems to be either to run it from the parent directory of furniture with: > > python -m furniture.chair.build_chair Yes. More pedantically, run it from somewhere such that the furniture package is importable. For example, if you install furniture, then it's accessible everywhere. > However, I don't see having a separate single main.py outside my package would work with keeping my code tidy/organised, and or how it'd work with the other files (config.yaml, or create_table.sql) which are associated with each script? The other files are contained within the package. As long as build_table looks in the right places, they'll still be accessible. (e.g. http://docs.python.org/2/library/pkgutil#pkgutil.get_data ). > A third way I thought of way just to create a setup.py and install the package into site-packages - and then everything will work? However, I don't think that solves my problem of understanding how things work, or getting my directory structure right. No, installing furniture won't change anything about how you need to run it. Either you run a separate script that imports it and runs the right main function, or you use python -m furniture.foo.bar > Although apparently running a script inside a package is an anti-pattern? (https://mail.python.org/pipermail/python-3000/2007-April/006793.html) It's not an antipattern, it's just plain broken. Some things stop working as you'd expect, like exception handling. > How would you guys organise the code above? If I really cared about the command line interface, I would probably reorganize something like this: furniture/ - __init__.py - __main__.py - common.py * chair/ - __init__.py - build.py - create.sql - config.yaml * furniture/ - __init__.py - build.py - create.sql - config.yaml And then create chairs by running `python -m furniture build chair`. furniture/__main__.py would dynamically import furniture.chair.build and run furniture.chair.build.main(). There would also be an executable I might install separately, furniture, the contents of which are "from furniture import __main__; __main__.main()" > Also, if I have tests (say with pyttest), inside furniture/table/tests/test_table.py, how would I run these as well? If I run py.test from there, I get the same: > > $ py.test > .... > from ..table.build_table import Table > E ValueError: Attempted relative import in non-package > .... > > (Above is just an extract). > > Assuming I use pytest, where should my tests be in the directory structure, and how should I be running them? As far as I understand py.test and nose, they are designed such that you don't put your tests as subpackages. If you want to put your tests as subpackages, use a different unit testing framework, like unittest. Then you can just do `python -m unittest discover .` If you do want to use py.test (or nose), then either there is some flag you need to pass in that I'm not aware of, or your directory structure should be: my-project/ - README - LICENSE - setup.py * furniture/ ... * tests/ - test_chair.py - test_common.py - test_table.py Note that tests is not a package either. py.test and nose work by loading files, NOT modules. So they won't work with loading test submodules in a package. For this and other reasons, I personally stay away from nose and py.test. -- Devin