diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 51b0369d1..938247df6 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -7,7 +7,7 @@ on: jobs: test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: matrix: ruby-version: ['2.7', '3.0', '3.1', '3.4'] @@ -20,7 +20,8 @@ jobs: with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - - run: | + - name: Run test suite + run: | if [ ! -z "$RUNNER_DEBUG" ] ; then DEBUG=1 bundle exec rspec -fd else diff --git a/docs/installation.rst b/docs/installation.rst index 4ce42aa43..23a0e205b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -36,6 +36,7 @@ Some package formats require other tools to be installed on your machine to be b * RPM: rpm/rpm-tools/rpm-build [This dependency might be removed in the future, see `issue #54`_ on github] * Snap: squashfs/squashfs-tools +* Python: a requirements.txt file is provided to list Python dependencies: `$ pip install -r requirements.txt` .. _issue #54: https://github.com/jordansissel/fpm/issues/54 diff --git a/lib/fpm/package/pyfpm/get_metadata.py b/lib/fpm/package/pyfpm/get_metadata.py deleted file mode 100644 index 7347e0c9b..000000000 --- a/lib/fpm/package/pyfpm/get_metadata.py +++ /dev/null @@ -1,115 +0,0 @@ -from distutils.core import Command -import os -import sys -import pkg_resources -try: - import json -except ImportError: - import simplejson as json - -PY3 = sys.version_info[0] == 3 - -if PY3: - def u(s): - return s -else: - def u(s): - if isinstance(u, unicode): - return u - return s.decode('utf-8') - - -# 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 = [ - ('load-requirements-txt', 'l', - "load dependencies from requirements.txt"), - ("output=", "o", "output destination for metadata json") - ] - boolean_options = ['load-requirements-txt'] - - def initialize_options(self): - self.load_requirements_txt = False - self.cwd = None - self.output = None - - def finalize_options(self): - 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 hasattr(dep, 'marker') and dep.marker: - # PEP0508 marker present - if not dep.marker.evaluate(): - return deps - - if dep.specs: - for operator, version in dep.specs: - deps.append("%s %s %s" % (dep.project_name, - 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": u("%s <%s>") % ( - u(self.distribution.get_author()), - u(self.distribution.get_author_email()), - ), - "description": self.distribution.get_description(), - "license": self.distribution.get_license(), - "url": self.distribution.get_url(), - } - - if self.distribution.has_ext_modules(): - data["architecture"] = "native" - else: - data["architecture"] = "all" - - final_deps = [] - - 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)) - if getattr(self.distribution, 'extras_require', None): - for dep in pkg_resources.parse_requirements( - v for k, v in self.distribution.extras_require.items() - if k.startswith(':') and pkg_resources.evaluate_marker(k[1:])): - final_deps.extend(self.process_dep(dep)) - - data["dependencies"] = final_deps - - output = open(self.output, "w") - if hasattr(json, 'dumps'): - def default_to_str(obj): - """ Fall back to using __str__ if possible """ - # This checks if the class of obj defines __str__ itself, - # so we don't fall back to an inherited __str__ method. - if "__str__" in type(obj).__dict__: - return str(obj) - return json.JSONEncoder.default(self, obj) - - output.write(json.dumps(data, indent=2, default=default_to_str)) - else: - # For Python 2.5 and Debian's python-json - output.write(json.write(data)) - output.close() diff --git a/lib/fpm/package/pyfpm/parse_requires.py b/lib/fpm/package/pyfpm/parse_requires.py index 22cb17868..c375ac4d0 100644 --- a/lib/fpm/package/pyfpm/parse_requires.py +++ b/lib/fpm/package/pyfpm/parse_requires.py @@ -2,6 +2,7 @@ #import pkg_resources import packaging.requirements +import packaging.markers import json import sys @@ -11,10 +12,9 @@ # Process environment markers, if any, and produce a list of requirements for the current environment. def evaluate_requirements(fd): all_requirements = [packaging.requirements.Requirement(line) for line in sys.stdin] - + default_env = packaging.markers.default_environment() for req in all_requirements: - # XXX: Note: marker.evaluate() can be given a dict() containing environment values to overwrite - if req.marker is None or req.marker.evaluate(): + if req.marker is None or req.marker.evaluate(environment=default_env): if len(req.specifier) > 0: for spec in req.specifier: yield "%s%s" % (req.name, spec) diff --git a/lib/fpm/package/python.rb b/lib/fpm/package/python.rb index 3e70be023..2e81aa5e3 100644 --- a/lib/fpm/package/python.rb +++ b/lib/fpm/package/python.rb @@ -605,7 +605,7 @@ def install_to_staging(path) flags = [ "--root", staging_path ] flags += [ "--prefix", prefix ] if !attributes[:prefix].nil? - safesystem(*attributes[:python_pip], "install", "--no-deps", *flags, path) + safesystem(*attributes[:python_pip], "install", "--no-deps", "--ignore-installed", *flags, path) end # def install_to_staging public(:input) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..ff0116abb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# Listing of fpm's Python package dependencies +packaging diff --git a/spec/fpm/package/deb_spec.rb b/spec/fpm/package/deb_spec.rb index 687dedf92..30fb20a15 100644 --- a/spec/fpm/package/deb_spec.rb +++ b/spec/fpm/package/deb_spec.rb @@ -400,7 +400,7 @@ def dpkg_field(field) subject.attributes[:deb_user] = "root" subject.attributes[:deb_group] = "root" subject.category = "comm" - subject.dependencies << "lsb-base" + subject.dependencies << "debconf" subject.instance_variable_set(:@staging_path, staging_path) diff --git a/spec/requirements.txt b/spec/requirements.txt new file mode 100644 index 000000000..2ba2e4247 --- /dev/null +++ b/spec/requirements.txt @@ -0,0 +1,2 @@ +# Listing of fpm test-suite's Python package dependencies +setuptools