Repository: mitmproxy/mitmproxy

Issue:
mitmproxy-0.10.1.tar.gz contains libmproxy.protocol *.pyc files.
libmproxy.protocol doesn't exist in 0.10. However, git keeps the folder after a branch switch as the pyc files are on gitignore and thereby not removed. Now, I suspect that setuptools normally takes the .py files, but resort to the .pyc version if the .py one isn't available. As a result, the 0.10.1 release contains compiled pyc files for libmproxy.protocol. We had two bug reports lately which used an 0.11 example script which caused an import of libmproxy.protocol, e.g.

```
>>> import libmproxy.protocol
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/aldo/mitmproxy/mitmproxy/libmproxy/protocol/__init__.py", line 1, in <module>    
ImportError: cannot import name AddressPriority
```

The first guy got fairly confused when I called him Aldo :stuck_out_tongue: .



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,80 +1,15 @@
-from distutils.core import setup
-import fnmatch, os.path
+from setuptools import setup, find_packages
+from codecs import open
+import os
 from libmproxy import version
 
+# Based on https://github.com/pypa/sampleproject/blob/master/setup.py
+# and https://python-packaging-user-guide.readthedocs.org/
 
-def pdir():
-    dirname, _ = os.path.split(__file__)
-    return os.path.abspath(dirname)
+here = os.path.abspath(os.path.dirname(__file__))
 
-
-def _fnmatch(name, patternList):
-    for i in patternList:
-        if fnmatch.fnmatch(name, i):
-            return True
-    return False
-
-
-def _splitAll(path):
-    parts = []
-    h = path
-    while 1:
-        if not h:
-            break
-        h, t = os.path.split(h)
-        parts.append(t)
-    parts.reverse()
-    return parts
-
-
-def findPackages(path, dataExclude=[]):
-    """
-        Recursively find all packages and data directories rooted at path. Note
-        that only data _directories_ and their contents are returned -
-        non-Python files at module scope are not, and should be manually
-        included.
-
-        dataExclude is a list of fnmatch-compatible expressions for files and
-        directories that should not be included in pakcage_data.
-
-        Returns a (packages, package_data) tuple, ready to be passed to the
-        corresponding distutils.core.setup arguments.
-    """
-    packages = []
-    datadirs = []
-    for root, dirs, files in os.walk(path, topdown=True):
-        if "__init__.py" in files:
-            p = _splitAll(root)
-            packages.append(".".join(p))
-        else:
-            dirs[:] = []
-            if packages:
-                datadirs.append(root)
-
-    # Now we recurse into the data directories
-    package_data = {}
-    for i in datadirs:
-        if not _fnmatch(i, dataExclude):
-            parts = _splitAll(i)
-            module = ".".join(parts[:-1])
-            acc = package_data.get(module, [])
-            for root, dirs, files in os.walk(i, topdown=True):
-                sub = os.path.join(*_splitAll(root)[1:])
-                if not _fnmatch(sub, dataExclude):
-                    for fname in files:
-                        path = os.path.join(sub, fname)
-                        if not _fnmatch(path, dataExclude):
-                            acc.append(path)
-                else:
-                    dirs[:] = []
-            package_data[module] = acc
-    return packages, package_data
-
-
-with open(os.path.join(pdir(), "README.txt")) as f:
+with open(os.path.join(here, 'README.txt'), encoding='utf-8') as f:
     long_description = f.read()
-packages, package_data = findPackages("libmproxy")
-
 
 scripts = ["mitmdump"]
 if os.name != "nt":
@@ -86,7 +21,8 @@ def findPackages(path, dataExclude=[]):
     "requests>=2.4.0",
     "pyOpenSSL>=0.14",
     "Flask>=0.10.1",
-    "tornado>=4.0.2"
+    "tornado>=4.0.2",
+    "sortedcontainers>=0.9.1"
 }
 script_deps = {
     "mitmproxy": {
@@ -100,8 +36,10 @@ def findPackages(path, dataExclude=[]):
     deps.update(script_deps[script])
 if os.name == "nt":
     deps.add("pydivert>=0.0.4")  # Transparent proxying on Windows
-console_scripts = ["%s = libmproxy.main:%s" % (s, s) for s in scripts]
 
+console_scripts = [
+    "%s = libmproxy.main:%s" % (s, s) for s in scripts
+]
 
 
 setup(
@@ -109,11 +47,10 @@ def findPackages(path, dataExclude=[]):
     version=version.VERSION,
     description="An interactive, SSL-capable, man-in-the-middle HTTP proxy for penetration testers and software developers.",
     long_description=long_description,
+    url="http://mitmproxy.org",
     author="Aldo Cortesi",
     author_email="aldo@corte.si",
-    url="http://mitmproxy.org",
-    packages=packages,
-    package_data=package_data,
+    license="MIT",
     classifiers=[
         "License :: OSI Approved :: MIT License",
         "Development Status :: 5 - Production/Stable",
@@ -123,15 +60,21 @@ def findPackages(path, dataExclude=[]):
         "Operating System :: POSIX",
         "Programming Language :: Python",
         "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.7",
         "Topic :: Security",
         "Topic :: Internet",
         "Topic :: Internet :: WWW/HTTP",
         "Topic :: Internet :: Proxy Servers",
         "Topic :: Software Development :: Testing"
     ],
+
+    packages=find_packages(),
+    include_package_data=True,
+
     entry_points={
         'console_scripts': console_scripts
     },
+
     install_requires=list(deps),
     extras_require={
         'dev': [
@@ -147,4 +90,4 @@ def findPackages(path, dataExclude=[]):
             "cssutils>=1.0"
         ]
     }
-)
+)
\ No newline at end of file


Test patch: