Skip to content

Commit

Permalink
Merge pull request jordansissel#390 from r4um/fix_351
Browse files Browse the repository at this point in the history
Close jordansissel#351, Close jordansissel#307 Move requirements.txt handling to get_metadata.py
  • Loading branch information
jls committed Apr 9, 2013
2 parents 2a790d5 + 25785a1 commit 819292e
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 39 deletions.
2 changes: 1 addition & 1 deletion lib/fpm/package/pyfpm/__init__.py
@@ -1 +1 @@
__all__ = [ "list_dependencies" ]
__all__ = [ "get_metadata" ]
58 changes: 41 additions & 17 deletions lib/fpm/package/pyfpm/get_metadata.py
@@ -1,4 +1,5 @@
from distutils.core import Command
import os
import pkg_resources
try:
import json
Expand All @@ -10,23 +11,49 @@
# possible some of my techniques below are outdated or bad.
# If you have fixes, let me know.


class get_metadata(Command):
description = "get package metadata"
user_options = []
user_options = [
('load-requirements-txt', 'l',
"load dependencies from requirements.txt"),
]
boolean_options = ['load-requirements-txt']

def initialize_options(self):
pass
self.load_requirements_txt = False
self.cwd = None

def finalize_options(self):
pass
self.cwd = os.getcwd()
self.requirements_txt = os.path.join(self.cwd, "requirements.txt")
# make sure we have a requirements.txt
if self.load_requirements_txt:
self.load_requirements_txt = os.path.exists(self.requirements_txt)

def process_dep(self, dep):
deps = []
if dep.specs:
for operator, version in dep.specs:
final_operator = operator

if operator == "==":
final_operator = "="

deps.append("%s %s %s" % (dep.project_name,
final_operator, version))
else:
deps.append(dep.project_name)

return deps

def run(self):
data = {
"name": self.distribution.get_name(),
"version": self.distribution.get_version(),
"author": "%s <%s>" % (
self.distribution.get_author(),
self.distribution.get_author_email()
self.distribution.get_author_email(),
),
"description": self.distribution.get_description(),
"license": self.distribution.get_license(),
Expand All @@ -39,19 +66,16 @@ def run(self):
data["architecture"] = "all"

final_deps = []
if getattr(self.distribution, 'install_requires', None):
for dep in pkg_resources.parse_requirements(
self.distribution.install_requires):
# add all defined specs to the dependecy list separately.
if dep.specs:
for operator, version in dep.specs:
final_deps.append("%s %s %s" % (
dep.project_name,
(lambda x: "=" if x == "==" else x)(operator),
version
))
else:
final_deps.append(dep.project_name)

if self.load_requirements_txt:
requirement = open(self.requirements_txt).readlines()
for dep in pkg_resources.parse_requirements(requirement):
final_deps.extend(self.process_dep(dep))
else:
if getattr(self.distribution, 'install_requires', None):
for dep in pkg_resources.parse_requirements(
self.distribution.install_requires):
final_deps.extend(self.process_dep(dep))

data["dependencies"] = final_deps

Expand Down
30 changes: 9 additions & 21 deletions lib/fpm/package/python.rb
Expand Up @@ -150,10 +150,17 @@ def load_package_info(setup_py)
output = ::Dir.chdir(setup_dir) do
setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} " \
"setup.py --command-packages=pyfpm get_metadata"

if attributes[:python_obey_requirements_txt?]
setup_cmd += " --load-requirements-txt"
end

# Capture the output, which will be JSON metadata describing this python
# package. See fpm/lib/fpm/package/pyfpm/get_metadata.py for more
# details.
output = `#{setup_cmd}`
@logger.info("fetching package metadata", :setup_cmd => setup_cmd)

output = %x{#{setup_cmd}}
if !$?.success?
@logger.error("setup.py get_metadata failed", :command => setup_cmd,
:exitcode => $?.exitcode)
Expand Down Expand Up @@ -184,27 +191,8 @@ def load_package_info(setup_py)
# convert python-Foo to python-foo if flag is set
self.name = self.name.downcase if attributes[:python_downcase_name?]

requirements_txt = File.join(setup_dir, "requirements.txt")
if !attributes[:no_auto_depends?] && attributes[:python_obey_requirements_txt?] && File.exists?(requirements_txt)
@logger.info("Found requirements.txt, using it instead of setup.py " \
"for dependency information", :path => requirements_txt)
@logger.debug("Clearing dependency list (from setup.py) in prep for " \
"reading requirements.txt")
# Best I can tell, requirements.txt are a superset of what
# is already supported as 'dependencies' in setup.py
# So we'll parse them the same way below.

# requirements.txt can have dependencies, flags, and comments.
# We only want the comments, so remove comment and flag lines.
metadata["dependencies"] = File.read(requirements_txt).split("\n") \
.reject { |l| l =~ /^\s*$/ } \
.reject { |l| l =~ /^\s*#/ } \
.reject { |l| l =~ /^-/ } \
.map(&:strip)
end

if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
self.dependencies += metadata["dependencies"].collect do |dep|
self.dependencies = metadata["dependencies"].collect do |dep|
dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
match = dep_re.match(dep)
if match.nil?
Expand Down

0 comments on commit 819292e

Please sign in to comment.