Ejemplo n.º 1
0
def test_first_word():
    assert setupmeta.relative_path(None) is None
    assert setupmeta.relative_path("") == ""
    assert setupmeta.relative_path("foo") == "foo"

    assert setupmeta.first_word(None) is None
    assert setupmeta.first_word("") is None
    assert setupmeta.first_word("  \n \t ") is None
    assert setupmeta.first_word("  \n \t foo[bar]") == "foo"
    assert setupmeta.first_word("FOO bar") == "foo"
    assert setupmeta.first_word(" FOO, bar") == "foo"
    assert setupmeta.first_word("123") == "123"
Ejemplo n.º 2
0
 def auto_fill_entry_points(self, key="entry_points"):
     if self.pkg_info.entry_points_txt:
         self.add_definition(key,
                             load_contents(self.pkg_info.entry_points_txt),
                             relative_path(self.pkg_info.entry_points_txt))
     path = "%s.ini" % key
     self.add_definition(key, load_contents(path), path)
Ejemplo n.º 3
0
 def delete(self, full_path):
     if os.path.isdir(full_path):
         shutil.rmtree(full_path)
         print("deleted %s" % setupmeta.relative_path(full_path))
     else:
         os.unlink(full_path)
         self.by_ext[full_path.rpartition(".")[2]] += 1
     self.deleted += 1
Ejemplo n.º 4
0
    def __init__(self, path):
        self.source = relative_path(path)
        self.reqs = load_list(path)
        self.links = None

        if any(self.is_complex_requirement(line) for line in self.reqs):
            reqs, links = self.parse_requirements(path)
            if reqs:
                self.reqs = reqs
                self.links = links
Ejemplo n.º 5
0
    def __init__(self, path, abstract=False):
        """
        :param str path: Path to req file
        :param bool abstract: If True, abstract away simple pinning (applicable to install_requires only)
        """
        self.source = relative_path(path)
        self.notes = {}
        self.reqs = []
        self.abstracted = []
        self.untouched = []
        self.ignored = []
        self.links = None

        if abstract:
            self.parse_with_comments()

        else:
            reqs, links = parse_requirements(path)
            if reqs:
                self.reqs = reqs
                self.links = links
Ejemplo n.º 6
0
    def finalize(self, upstream):
        self.attrs.update(MetaDefs.dist_to_dict(upstream))

        self.find_project_dir(self.attrs.pop("_setup_py_path", None))
        scm = self.attrs.pop("scm", None)

        # Add definitions from setup()'s attrs (highest priority)
        for key, value in self.attrs.items():
            if key not in self.definitions:
                self.add_definition(key, value, EXPLICIT)

        # Add definitions from PKG-INFO, when available
        self.pkg_info = PackageInfo(MetaDefs.project_dir)
        for key, value in self.pkg_info.info.items():
            if key in MetaDefs.all_fields:
                self.add_definition(key, value,
                                    relative_path(self.pkg_info.path))

        # Allow to auto-fill 'name' from setup.py's __title__, if any
        self.merge(SimpleModule("setup.py"))
        title = self.definitions.get("title")
        if title:
            self.auto_fill("name", title.value, source=title.source)

        if "--name" in sys.argv[1:3]:
            # No need to waste time auto-filling anything if all we need to show is package name
            return self

        packages = self.attrs.get("packages", [])
        py_modules = self.attrs.get("py_modules", [])

        if not packages and not py_modules and self.name:
            # Try to auto-determine a good default from 'self.name'
            name = self.pythonified_name
            src_folder = project_path("src")
            if os.path.isdir(src_folder):
                packages = setuptools.find_packages(where=src_folder)
                if os.path.isfile(project_path("src", "%s.py" % name)):
                    py_modules = [name]

                if packages or py_modules:
                    self.auto_fill("package_dir", {"": "src"})

            else:
                src_folder = project_path()
                packages = setuptools.find_packages(where=src_folder)
                if packages:
                    # Take only found packages that start with the expected name
                    # For any other use-case, user must explicitly list their packages
                    packages = [p for p in packages if p.startswith(name)]

                if os.path.isfile(project_path("%s.py" % name)):
                    py_modules = [name]

            if packages:
                self.auto_fill("packages", sorted(packages))

            if py_modules:
                self.auto_fill("py_modules", py_modules)

        # Scan the usual/conventional places
        for py_module in py_modules:
            self.merge(SimpleModule("%s.py" % py_module))

        for package in packages:
            if package and "." not in package:
                # Look at top level modules only
                self.merge(
                    SimpleModule(package, "__about__.py"),
                    SimpleModule(package, "__version__.py"),
                    SimpleModule(package, "__init__.py"),
                    SimpleModule("src", package, "__about__.py"),
                    SimpleModule("src", package, "__version__.py"),
                    SimpleModule("src", package, "__init__.py"),
                )

        if not self.name:
            warn(
                "'name' not specified in setup.py, auto-fill will be incomplete"
            )

        elif not self.definitions.get("packages") and not self.definitions.get(
                "py_modules"):
            warn(
                "No 'packages' or 'py_modules' defined, this is an empty python package"
            )

        scm = scm or project_scm(MetaDefs.project_dir)
        self.versioning = Versioning(self, scm)
        self.versioning.auto_fill_version()

        self.fill_urls()

        self.auto_adjust("author", self.extract_email)
        self.auto_adjust("contact", self.extract_email)
        self.auto_adjust("maintainer", self.extract_email)

        self.requirements = Requirements(self.pkg_info)
        self.auto_fill_requires("install_requires")
        self.auto_fill_requires("tests_require")
        if self.requirements.dependency_links:
            self.auto_fill("dependency_links",
                           self.requirements.dependency_links,
                           self.requirements.links_source)

        self.auto_fill_classifiers()
        self.auto_fill_entry_points()
        self.auto_fill_license()
        self.auto_fill_long_description()
        self.auto_fill_include_package_data()
        self.sort_classifiers()

        return self
Ejemplo n.º 7
0
    def __init__(self, path, abstract=False):
        """
        :param str path: Path to req file
        :param bool abstract: If True, abstract away simple pinning (applicable to install_requires only)
        """
        self.source = relative_path(path)
        current_section = None
        self.notes = {}
        self.reqs = []
        self.abstracted = []
        self.untouched = []
        self.ignored = []
        for line in load_list(path, comment=None):
            if not abstract:
                # Not abstracting, just trim away comments
                if line.startswith("#"):
                    continue
                if "# " in line:
                    i = line.index("# ")
                    line = line[:i].strip()
                if line:
                    self.reqs.append(line)
                continue

            # We're abstracting, allow comments to tweak how we do that
            if line.startswith("#"):
                # Lines containing only a comment can start a "section", all requirements below this will respect that section
                word = first_word(line[1:])
                if word in KNOWN_SECTIONS:
                    current_section = word
                continue

            line_section = current_section
            note = None
            if "# " in line:
                # Trailing comments can direct us to treat that particular line in a certain way regarding pinning
                i = line.index("# ")
                word = first_word(line[i + 2:])
                line = line[:i].strip()
                if word in KNOWN_SECTIONS:
                    line_section = word
                    note = "'%s' stated on line" % word

            if line_section == "indirect":
                # 'indirect' means the pinning was done to satisfy some indirect dependency,
                # but should not be considered as our project's dep
                self.ignored.append("%s # %s" %
                                    (line, note or "indirect section"))
                continue

            if (not line_section
                    or line_section == "abstract") and "==" in line:
                # By default (or if in explicit 'abstract' section), trim away simple '==' pinning
                i = line.index("==")
                line = line[:i].strip()
                if not note:
                    if line_section:
                        note = "in '%s' section" % line_section
                    else:
                        note = "abstracted by default"
                self.abstracted.append("%s # %s" % (line, note))

            elif line and (line[0].isalnum() or line.startswith("-e")):
                # Count as untouched only actual deps (ignore flags such as -i)
                if note:
                    self.untouched.append("%s # %s" % (line, note))
                else:
                    self.untouched.append(line)

            if note:
                self.notes[line] = note or "abstract by default"

            self.reqs.append(line)

        self.links = None

        if any(is_complex_requirement(line) for line in self.reqs):
            reqs, links = parse_requirements(self.reqs)
            if reqs:
                self.reqs = reqs
                self.links = links