Check-in [aeb6d189f6]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | - Add python packaging support. * Uses 'easy_install' to download packages from pypi. * You can also give the path to a setup.py to use if you already have the project locally. * Automatically chooses 'native' or 'all' arch depending on whether the python project has C extensions |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
aeb6d189f6149d963c236de71e21c295 |
User & Date: | jls@semicomplete.com 2011-05-17 01:18:04 |
Context
2011-05-17
| ||
01:20 | Merge branch 'master' of github.com:jordansissel/fpm check-in: 0488918f3c user: jls@semicomplete.com tags: trunk | |
01:18 | - Add python packaging support. * Uses 'easy_install' to download packages from pypi. * You can also give the path to a setup.py to use if you already have the project locally. * Automatically chooses 'native' or 'all' arch depending on whether the python project has C extensions check-in: aeb6d189f6 user: jls@semicomplete.com tags: trunk | |
01:15 | - ignore pyc check-in: e046e6d55c user: jls@semicomplete.com tags: trunk | |
Changes
Changes to lib/fpm.rb.
1 2 3 4 5 6 7 8 9 10 11 | require "fpm/namespace" require "fpm/builder" require "fpm/package" require "fpm/target/deb" require "fpm/target/rpm" require "fpm/source" require "fpm/source/dir" require "fpm/source/gem" require "fpm/source/rpm" | > | 1 2 3 4 5 6 7 8 9 10 11 12 | require "fpm/namespace" require "fpm/builder" require "fpm/package" require "fpm/target/deb" require "fpm/target/rpm" require "fpm/source" require "fpm/source/dir" require "fpm/source/gem" require "fpm/source/python" require "fpm/source/rpm" |
Changes to lib/fpm/builder.rb.
︙ | ︙ | |||
88 89 90 91 92 93 94 | ::Dir.chdir(builddir) do @package.build!({ :tarball => tar_path, :output => output }) end | | > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | ::Dir.chdir(builddir) do @package.build!({ :tarball => tar_path, :output => output }) end garbage << @source.garbage if @source.respond_to?(:garbage) cleanup! end # def assemble! private def builddir @builddir ||= File.expand_path( "#{Dir.pwd}/build-#{@package.type}-#{File.basename(output)}" ) |
︙ | ︙ |
Added lib/fpm/source/pyfpm/__init__.py.
> | 1 | __all__ = [ "list_dependencies" ] |
Added lib/fpm/source/pyfpm/get_metadata.py.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | from distutils.core import Command import json import re # Note, the last time I coded python daily was at Google, so it's entirely # 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 = [] def initialize_options(self): pass # def initialize_options def finalize_options(self): pass # def finalize_options def run(self): #print type(self.distribution) #for i in sorted(dir(self.distribution)): #if i.startswith("_"): #continue ###print "%s: %r" % (i, self.__getattr__(i)) #print "%s" % i data = { "name": self.distribution.get_name(), "version": self.distribution.get_version(), "author": "%s <%s>" % (self.distribution.get_author(), self.distribution.get_author_email()), "description": self.distribution.get_description(), "license": self.distribution.get_license(), "url": self.distribution.get_url(), } # If there are python C/extension modules, we'll want to build a native # arch package. if self.distribution.has_ext_modules(): data["architecture"] = "native" else: data["architecture"] = "all" # end if dependencies = [] try: dependencies = self.distribution.install_requires except: pass final_deps = [] dep_re = re.compile("([^<>= ]+)\s*([<>=]{1,2})\s*(.*)$") for dep in dependencies: # python deps are strings that look like: # "packagename" # "packagename >= version" # Replace 'packagename' with 'python#{suffix}-packagename' m = dep_re.match(dep) if len(m.groups()) == 1: name, cond, version = m.groups()[0], ">=", 0 else: name, cond, version = m.groups() # end if final_deps.append("%s %s %s" % (name, cond, version)) # end for i in dependencies data["dependencies"] = final_deps #print json.dumps(data, indent=2) print json.dumps(data, indent=2) # def run # class list_dependencies |
Added lib/fpm/source/python.rb.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | require "fpm/namespace" require "fpm/source" require "rubygems/package" require "rubygems" require "fileutils" require "tmpdir" require "json" class FPM::Source::Python < FPM::Source def get_source(params) package = @paths.first if ["setup.py", "."].include?(package) # Assume we're building from an existing python package. # Source already acquired, nothing to do! return end if !File.exists?(package) download(package) end end # def get_source def download(package) puts "Trying to download #{package} (using easy_install)" @tmpdir = ::Dir.mktmpdir("python-build", ::Dir.pwd) system("easy_install", "--editable", "--build-directory", @tmpdir, package) # easy_install will put stuff in @tmpdir/packagename/, flatten that. # That is, we want @tmpdir/setup.py, and start with # @tmpdir/somepackage/setup.py dirs = ::Dir.glob(File.join(@tmpdir, "*")) if dirs.length != 1 raise "Unexpected directory layout after easy_install. Maybe file a bug? The directory is #{@tmpdir}" end @paths = dirs end # def download def get_metadata setup_py = @paths.first if File.directory?(setup_py) setup_py = File.join(setup_py, "setup.py") @paths = [setup_py] end if !File.exists?(setup_py) raise "Unable to find python package; tried #{setup_py}" end pylib = File.expand_path(File.dirname(__FILE__)) setup_cmd = "env PYTHONPATH=#{pylib} python #{setup_py} --command-packages=pyfpm get_metadata" output = ::Dir.chdir(File.dirname(setup_py)) { `#{setup_cmd}` } puts output metadata = JSON.parse(output[/\{.*\}/msx]) #p metadata self[:architecture] = metadata["architecture"] self[:description] = metadata["description"] self[:license] = metadata["license"] self[:version] = metadata["version"] self[:name] = "python#{self[:suffix]}-#{metadata["name"]}" self[:url] = metadata["url"] self[:dependencies] = metadata["dependencies"] end # def get_metadata def make_tarball!(tar_path, builddir) setup_py = @paths.first dir = File.dirname(setup_py) # Some setup.py's assume $PWD == current directory of setup.py, so let's # chdir first. ::Dir.chdir(dir) do system("python", "setup.py", "bdist") end dist_tar = ::Dir.glob(File.join(dir, "dist", "*.tar.gz")).first puts "Found dist tar: #{dist_tar}" puts "Copying to #{tar_path}" @paths = [ "." ] system("cp", dist_tar, "#{tar_path}.gz") end # def make_tarball! def garbage trash = [] trash << @tmpdir if @tmpdir return trash end # def garbage end # class FPM::Source::Gem |