#12 improved man pages and some minor points. First steps to an unification for openSUSE and Fedora
Opened 5 years ago by dsteuer. Modified 4 years ago
dsteuer/r2spec master  into  master

file modified
+5 -5
@@ -2,7 +2,7 @@ 

  # R2spec 

  #

  # R2spec is made to help to the creation of R specfile

- # It works from a source file (*.tar.gz) or a url (http://...*.tar.gz)

+ # It works from a source file (*.tar.gz) or a url (https://...*.tar.gz)

  #

  #

  # Made the 13th February 2008
@@ -141,11 +141,11 @@ 

  #       - Fill the url

  #   * Add %define BioC for the Bioconductor release of Bioconductor packages

  #   * Add check if the package is noarch or not

- #   * Add oportunity to copy the source in the %_topdir defined in .rpmmacros

+ #   * Add opportunity to copy the source in the %_topdir defined in .rpmmacros

  #   * Add a parameter in the config file for the version on Bioconductor used

  #   * Add a Spec class to write the spec file

  #   * Add a Noarch class that inherit the Spec class and handle the noarch package case

- #   * Ask what to do if the specfile is alreay in the current working directory

+ #   * Ask what to do if the specfile is already in the current working directory

  #

  # -Bugs correction

  #   * Catch the Description in the file DESCRIPTION when it is on several lines
@@ -202,10 +202,10 @@ 

  #

  # Distributed under License GPLv3 or later

  # You can find a copy of this license on the website

- # http://www.gnu.org/licenses/gpl.html

+ # https://www.gnu.org/licenses/gpl.html

  #

  # This software has been based on the guidelines for R packaging

- # http://fedoraproject.org/wiki/Packaging/R

+ # https://docs.fedoraproject.org/en-US/packaging-guidelines/R/

  #

  #***********************************************

  

file modified
+4 -4
@@ -28,7 +28,7 @@ 

  

  ** Install R2spec from the RPM **

      Get the latest RPM from

-         https://fedorahosted.org/r2spec/

+         https://pagure.io/r2spec/

  

      Run the command in the directory where your rpm file has been downloaded

          su -c'rpm -ivh R2spec-*.rpm'
@@ -39,7 +39,7 @@ 

      The simplest is then to reconstruct the RPM.

  

      Get the latest src.rpm from

-         https://fedorahosted.org/r2spec/

+         https://pagure.io/r2spec/

  

      Make sure that you have rpmbuild available and run this command if needed

          su -c'yum install rpm-build'
@@ -51,14 +51,14 @@ 

  

  ** Install R2spec from the source in a RPM-based system **

      Get the latest source from

-         https://fedorahosted.org/r2spec/

+         https://pagure.io/r2spec/

  

      Run the command in the directory where your source file has been downloaded

          rpmbuild -ta R2spec-*.tar.gz

  

  ** Install R2spec from the source using python installer **

      Get the latest source from

-         https://fedorahosted.org/r2spec/

+         https://pagure.io/r2spec/

  

      In the directory where your source file has been downloaded:

      Open the tarball

file modified
+4 -5
@@ -1,7 +1,7 @@ 

                      GNU GENERAL PUBLIC LICENSE

                         Version 3, 29 June 2007

  

-  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>

+  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>

   Everyone is permitted to copy and distribute verbatim copies

   of this license document, but changing it is not allowed.

  
@@ -645,7 +645,7 @@ 

      GNU General Public License for more details.

  

      You should have received a copy of the GNU General Public License

-     along with this program.  If not, see <http://www.gnu.org/licenses/>.

+     along with this program.  If not, see <https://www.gnu.org/licenses/>.

  

  Also add information on how to contact you by electronic and paper mail.

  
@@ -664,12 +664,11 @@ 

    You should also get your employer (if you work as a programmer) or school,

  if any, to sign a "copyright disclaimer" for the program, if necessary.

  For more information on this, and how to apply and follow the GNU GPL, see

- <http://www.gnu.org/licenses/>.

+ <https://www.gnu.org/licenses/>.

  

    The GNU General Public License does not permit incorporating your program

  into proprietary programs.  If your program is a subroutine library, you

  may consider it more useful to permit linking proprietary applications with

  the library.  If this is what you want to do, use the GNU Lesser General

  Public License instead of this License.  But first, please read

- <http://www.gnu.org/philosophy/why-not-lgpl.html>.

- 

+ <https://www.gnu.org/licenses/why-not-lgpl.html>.

file removed
-11
@@ -1,11 +0,0 @@ 

- Metadata-Version: 1.1

- Name: R2spec

- Version: 4.2.1

- Summary: R2spec is a small python tool that generates spec file and rpm for R libraries.

- Home-page: https://fedorahosted.org/r2spec/

- Author: Pierre-Yves Chibon

- Author-email: pingou@pingoured.fr

- License: GPLv3+

- Download-URL: https://fedorahosted.org/releases/r/2/r2spec/

- Description: UNKNOWN

- Platform: UNKNOWN

file modified
+9 -3
@@ -19,6 +19,10 @@ 

  

  """ R2rpm launcher script """

  

+ from __future__ import absolute_import, division, print_function

+ 

+ import sys

+ 

  from r2spec.r2spec_obj import R2rpm, setup_parser

  from r2spec import R2specError

  
@@ -26,6 +30,8 @@ 

      PARSER = setup_parser('R2rpm')

      ARG = PARSER.parse_args()

      try:

-         R2rpm().main(ARG)

-     except R2specError, err:

-         print err

+         ret = R2rpm().main(ARG)

+     except R2specError as err:

+         print(err)

+         ret = 1

+     sys.exit(ret)

file modified
+2 -2
@@ -15,7 +15,7 @@ 

  .SH DESCRIPTION

  

  This tool generate RPM for R libraries according to the Fedora guidelines for R packaging.

- These guidelines are available at: https://fedoraproject.org/wiki/Packaging/R

+ These guidelines are available at: https://docs.fedoraproject.org/en-US/packaging-guidelines/R/

  

  .SH USAGE

  This program generates RPM file for R libraries for Fedora.
@@ -27,7 +27,7 @@ 

  contained in the sources are read (especially those contained in the DESCRIPTION

  file). The sources are then removed from the current working directory (unless

  specified otherwise).

- Finally the spec file is writen to the filesystem using the information collected.

+ Finally the spec file is written to the filesystem using the information collected.

  

  .HP

  R2rpm -u <url to sources>

file modified
+9 -3
@@ -19,6 +19,10 @@ 

  

  """ R2spec launcher script """

  

+ from __future__ import absolute_import, division, print_function

+ 

+ import sys

+ 

  from r2spec.r2spec_obj import R2spec, setup_parser

  from r2spec import R2specError

  
@@ -26,6 +30,8 @@ 

      PARSER = setup_parser('R2spec')

      ARG = PARSER.parse_args()

      try:

-         R2spec().main(ARG)

-     except R2specError, err:

-         print err

+         ret = R2spec().main(ARG)

+     except R2specError as err:

+         print(err)

+         ret = 1

+     sys.exit(ret)

file modified
+2 -2
@@ -15,7 +15,7 @@ 

  .SH DESCRIPTION

  

  This tool generate RPM spec file for R libraries according to the Fedora guidelines for R packaging.

- These guidelines are available at: https://fedoraproject.org/wiki/Packaging/R

+ These guidelines are available at: https://docs.fedoraproject.org/en-US/packaging-guidelines/R/

  

  .SH USAGE

  This program generates spec file for R libraries for Fedora.
@@ -27,7 +27,7 @@ 

  contained in the sources are read (especially those contained in the DESCRIPTION

  file). The sources are then removed from the current working directory (unless

  specified otherwise).

- Finally the spec file is writen to the filesystem using the information collected.

+ Finally the spec file is written to the filesystem using the information collected.

  

  .HP

  R2spec -u <url to sources>

file modified
+15 -3
@@ -2,14 +2,14 @@ 

  %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}

  

  Name:           R2spec

- Version:        4.2.1

+ Version:        5.0.0

  Release:        1%{?dist}

  Summary:        Python script to generate R spec file

  

  Group:          Development/Languages

  License:        GPLv3+

- URL:            https://fedorahosted.org/r2spec/

- Source0:        https://fedorahosted.org/releases/r/2/r2spec/R2spec-%{version}.tar.gz

+ URL:            https://pagure.io/r2spec

+ Source0:        https://releases.pagure.org/r2spec/R2spec-%{version}.tar.gz

  BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

  

  BuildArch:      noarch
@@ -56,6 +56,18 @@ 

  %{_mandir}/man1/R2rpm.1.gz

  

  %changelog

+ * Mon Sep 09 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.0.0-1

+ - Update to 5.0.0

+ - Port to python3

+ - Use textwrap to format package description

+ - Update the spec file for more recent standards

+ - Use https links

+ - Use rpm Suggests for R Suggests

+ - Disable explicit Requires/Suggests by default

+ - Use encoding from DESCRIPTION when reading it

+ - Update CRAN URL to use canonical form

+ - Check NeedsCompilation for arch dependence if available

+ 

  * Thu Jun 04 2015 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.2.1-1

  - Bump the version

  

file modified
+2 -2
@@ -1,5 +1,5 @@ 

  Name: R2spec

  Author: Pierre-Yves Chibon

  

- R2spec generates RPMs spec file for R libraries according to the R guidelines of Fedora available at http://fedoraproject.org/wiki/Packaging/R.

- It creates the spec file from an input which could be either a source file (*.tar.gz) or a url (http://*.tar.gz).

+ R2spec generates RPMs spec file for R libraries according to the R guidelines of Fedora available at https://docs.fedoraproject.org/en-US/packaging-guidelines/R/.

+ It creates the spec file from an input which could be either a source file (*.tar.gz) or a url (https://*.tar.gz).

file modified
+7 -4
@@ -19,6 +19,7 @@ 

  

  """ Miscellaneous functions used in R2spec. """

  

+ from __future__ import absolute_import, division, print_function

  

  import logging

  import shutil
@@ -27,7 +28,7 @@ 

  

  logging.basicConfig()

  LOG = logging.getLogger('R2spec')

- VERSION = '4.2.1'

+ VERSION = '5.0.0'

  

  

  def get_logger():
@@ -40,7 +41,8 @@ 

      Code from José Matos.

      :arg tag, the rpm tag to find the value of

      """

-     dirname = Popen(["rpm", "-E", '%' + tag], stdout=PIPE).stdout.read()[:-1]

+     dirname = Popen(["rpm", "-E", '%' + tag],

+                     stdout=PIPE, universal_newlines=True).stdout.read()[:-1]

      return dirname

  

  
@@ -48,7 +50,8 @@ 

      """" Calls mock to retrieve the root path and return it minus the last

      two levels.

      """

-     dirname = Popen(["mock", "--print-root-path"], stdout=PIPE).stdout.read()[:-1]

+     dirname = Popen(["mock", "--print-root-path"],

+                     stdout=PIPE, universal_newlines=True).stdout.read()[:-1]

      return dirname.rsplit('/', 3)[0] + '/'

  

  
@@ -64,7 +67,7 @@ 

      shutil.copyfile(fullpath, dest)

  

  

- class R2specError:

+ class R2specError(Exception):

      """ R2specError class

      Template for all the error of the project

      """

file modified
+13 -12
@@ -19,6 +19,7 @@ 

  

  """ Build related class and methods. """

  

+ from __future__ import absolute_import, division, print_function

  

  import os

  import subprocess
@@ -57,12 +58,12 @@ 

          if mock_config is None or mock_config is False:

              cmd = 'LANG=C rpmbuild -%s %s > %s 2>&1' % (rpmarg,

                  specname, self.buildlog)

-             self.log.debug(cmd)

+             self.log.debug('Running %s', cmd)

              self.outcode = subprocess.call(cmd, shell=True)

          else:

              cmd = 'LANG=C rpmbuild -bs %s > %s 2>&1' % (

                  specname, self.buildlog)

-             self.log.debug(cmd)

+             self.log.debug('Running %s', cmd)

              self.outcode = subprocess.call(cmd, shell=True)

              self.get_rpm()

  
@@ -74,7 +75,7 @@ 

                      mock_resultdir, name)

              cmd = 'LANG=C %s >> %s.build.log 2>&1' % (

                  mockcommand, specname)

-             self.log.debug(cmd)

+             self.log.debug('Running %s', cmd)

              self.outcode = subprocess.call(cmd, shell=True)

              if self.outcode == 30:

                  # When mock stop while building the cache, then check
@@ -90,7 +91,7 @@ 

                  directory = get_mock_root()

                  self.buildlog = '/%s/%s-%s/result/%s' % (

                      directory, mock_config, name, filename)

-             self.log.debug('buildlog %s' % self.buildlog)

+             self.log.debug('buildlog %s', self.buildlog)

  

      def get_rpm(self):

          """ Parses the build.log to extract the rpm generated.
@@ -108,9 +109,9 @@ 

                          self.rpm.append(rpm)

                      else:

                          self.rpm.append(rpm)

-         except IOError, err:

-             self.log.info('Could not read the file "%s"' % self.buildlog)

-             self.log.debug('ERROR: %s' % err)

+         except IOError as err:

+             self.log.info('Could not read the file "%s"', self.buildlog)

+             self.log.debug('ERROR: %s', err)

  

      def remove_logs(self):

          """ Remove the log file generated while building the RPM. """
@@ -131,10 +132,10 @@ 

              stream = open(self.buildlog, 'r')

              log = stream.read()

              stream.close()

-         except IOError, err:

-             self.log.info('An error occured during the build')

-             self.log.debug('ERROR: %s' % err)

-             print 'Stopping'

+         except IOError as err:

+             self.log.info('An error occurred during the build')

+             self.log.debug('ERROR: %s', err)

+             print('Stopping')

              return(1)

  

          logs = log.split('\n')
@@ -168,6 +169,6 @@ 

          if len(self.deps) == 0 and len(self.files) == 0 and self.outcode == 1:

              log = '%s.build.log' % specname

              raise BuildError(

-                 'An error occured at build time, see the log in %s' % log)

+                 'An error occurred at build time, see the log in %s' % log)

  

          return self.files

file modified
+38 -33
@@ -20,15 +20,19 @@ 

  Main functions for R2spec

  """

  

+ from __future__ import absolute_import, division, print_function

  

  import argparse

- import ConfigParser

  import logging

  import os

  import re

  import sys

  import pwd 

- from urlparse import urlparse

+ 

+ try:

+     import configparser

+ except ImportError:

+     import ConfigParser as configparser

  

  from r2spec.build import Build

  from r2spec.rpackage import RPackage
@@ -62,12 +66,13 @@ 

          help='Path to local sources of a R package.')

      parser.add_argument('--no-check', action='store_true',

          help='Do not include the %%check section in the generated spec file.')

-     parser.add_argument('--no-suggest', action='store_true',

-         help='Do not include the dependencies marked as \'Suggest\' by the source as dependencies of the RPM.')

+     parser.add_argument('--with-deps', action='store_true',

+         help='Include the dependencies marked by the source as dependencies of the RPM.')

      parser.add_argument('--force-dl', action='store_true',

          help='Enforce the download of the source, even if they are already on the system.')

      parser.add_argument('--keep-sources', action='store_true',

-         help='The extracted source on the current directory will not be removed.')

+                         help='The source will be extracted in the current '

+                              'directory.')

      parser.add_argument('--keep-logs', action='store_true',

          help='Keep the log file generated while building the rpm')

      parser.add_argument('--repo', default=None,
@@ -135,7 +140,7 @@ 

      except OSError:

          # os.getlogin() raises an exception when the session is not

          # in /var/run/utmp (non-login sessions)

-         if os.environ.has_key('LOGNAME'):

+         if 'LOGNAME' in os.environ:

              packager = os.environ['LOGNAME']

          else:

              packager = pwd.getpwuid(os.getuid())[0]
@@ -145,7 +150,7 @@ 

  

      def __init__(self):

          """Constructor of the Settings object.

-         This instanciate the Settings object and load into the _dict

+         This instantiates the Settings object and loads into the _dict

          attributes the default configuration which each available option.

          """

          self._dict = {
@@ -160,7 +165,7 @@ 

          :arg configfile, name of the configuration file loaded.

          :arg sec, section of the configuration retrieved.

          """

-         parser = ConfigParser.ConfigParser()

+         parser = configparser.RawConfigParser()

          configfile = os.environ['HOME'] + "/" + configfile

          is_new = create_conf(configfile)

          parser.read(configfile)
@@ -176,7 +181,7 @@ 

          :arg key, name of the parameter to set from the settings.

          :arg value, value of the parameter to set from the settings.

          """

-         if not key in self._dict.keys():

+         if key not in self._dict:

              raise KeyError(key)

          self._dict[key] = value

  
@@ -185,7 +190,7 @@ 

  

          :arg key, name of the parameter to retrieve from the settings.

          """

-         if not key in self._dict.keys():

+         if key not in self._dict:

              raise KeyError(key)

          return self._dict[key]

  
@@ -200,7 +205,7 @@ 

          else:

              opts = set()

  

-         for name in self._dict.iterkeys():

+         for name in self._dict:

              value = None

              if name in opts:

                  value = parser.get(section, name)
@@ -220,7 +225,7 @@ 

          self.log = get_logger()

  

      def main(self, args):

-         """ main fonction for R2spec.

+         """ Main function for R2spec.

          This is the method which actually runs R2spec and generate the

          spec file according to the argument given.

          """
@@ -232,7 +237,7 @@ 

              settings.set('email', args.email)

  

          if args.package:

-             pack = RPackage(re.sub('^R-', '', args.package))

+             pack = RPackage(re.sub(r'^R-', '', args.package))

              pack.search_package_in_repo()

          elif args.url:

              pack = RPackage(source0=args.url)
@@ -274,14 +279,13 @@ 

          if args.package or args.url:

              pack.download(args.force_dl)

  

-         pack.extract_sources()

+         if args.keep_sources:

+             pack.extract_sources()

          pack.get_description()

          pack.determine_arch()

-         if not args.keep_sources:

-             pack.remove_sources()

  

          spec = Spec(settings, pack, no_check=args.no_check,

-             no_suggest=args.no_suggest)

+                     with_deps=args.with_deps)

          spec.fill_spec_info()

          spec.get_template()

          spec.write_spec(True)
@@ -305,21 +309,21 @@ 

      def __check_build_output(self):

          """ Handle the output from the build, if it succeeded we stop

          otherwise the parse the error and act accordingly.

-         Return False if the build was successful, retun True otherwise.

+         Return False if the build was successful, return True otherwise.

          """

          specfile = self.spec.get_specfile()

          if self.build.outcode == 0:

-             self.log.info("RPM %s done" % specfile)

+             self.log.info("RPM %s done", specfile)

              # Get the list of rpm generated

              self.build.get_rpm()

-             print "RPM generated:"

-             print "\n".join(self.build.rpm)

+             print("RPM generated:")

+             print("\n".join(self.build.rpm))

              return False

          else:

              return True

  

      def main(self, args):

-         """ main fonction for R2rpm.

+         """ Main function for R2rpm.

          This is the method which actually runs R2rpm, it generates the

          spec files, cleans its %files section, build it and fill again

          the %files section.
@@ -327,7 +331,7 @@ 

  

          specfile = ''

          if args.package:

-             self.pack.name = re.sub('^R-', '', args.package)

+             self.pack.name = re.sub(r'^R-', '', args.package)

              self.spec.package = self.pack

              specfile = self.spec.get_specfile()

              self.pack.search_package_in_repo()
@@ -362,8 +366,9 @@ 

              # Generate the spec file

              self.pack = super(R2rpm, self).main(args)

          else:

-             self.log.info('Spec file "%s" is already there, no need to regenerate it'

-                 % specfile)

+             self.log.info(

+                 'Spec file "%s" is already there, no need to regenerate it',

+                 specfile)

  

          if args.package or args.url:

              self.pack.download(args.force_dl)
@@ -374,7 +379,7 @@ 

          self.spec.clean_files_section()

          self.spec.write_spec()

  

-         print 'Building... %s' % self.pack.name

+         print('Building... %s' % self.pack.name)

          self.build.build(specfile, mock_config=args.mock_config,

              mock_resultdir=args.mock_resultdir)

          if self.__check_build_output():
@@ -389,17 +394,17 @@ 

  

                  # Rebuild the package when build has failed the first time

                  if self.build.outcode:  # == 1 when build failed and 0 when build passed

-                     print 'Re-building... %s' % self.pack.name

+                     print('Re-building... %s' % self.pack.name)

                      self.build.build(specfile, mock_config=args.mock_config,

                          mock_resultdir=args.mock_resultdir)

                      self.__check_build_output()

-             except BuildDepencenciesError, err:

-                 print 'Missing dependencies to build %s' % self.pack.name

-                 self.log.info(err)

+             except BuildDepencenciesError as err:

+                 print('Missing dependencies to build %s' % self.pack.name)

+                 self.log.info('%s', err)

                  return 1

-             except BuildError, err:

-                 print 'An error occured during the build of %s' % self.pack.name

-                 self.log.debug('Build ERROR: %s' % err)

+             except BuildError as err:

+                 print('An error occurred during the build of %s' % self.pack.name)

+                 self.log.debug('Build ERROR: %s', err)

                  return 1

          if not args.keep_logs:

              self.build.remove_logs()

file modified
+99 -73
@@ -20,16 +20,21 @@ 

  R packages class.

  """

  

+ from __future__ import absolute_import, division, print_function

  

- import ConfigParser

  import os

  import re

- import shutil

  import sys

  import tarfile

- import urllib2

  

- from tarfile import TarError

+ try:

+     import configparser

+ except ImportError:

+     import ConfigParser as configparser

+ try:

+     import urllib.request as urllib_request

+ except ImportError:

+     import urllib2 as urllib_request

  

  from r2spec import get_logger, get_rpm_tag, R2specError

  
@@ -44,21 +49,21 @@ 

      """

      log = get_logger()

      try:

-         stream = urllib2.urlopen(url)

-         content = stream.read()

+         stream = urllib_request.urlopen(url)

+         content = stream.read().decode()

          stream.close()

-         sourcemotif = re.compile("Package:\s+%s\n" % name)

+         sourcemotif = re.compile(r"Package:\s+%s\n" % name)

          result = sourcemotif.search(content)

          if result is not None:

-             log.info("Package found in : %s" % url)

-             versionmotif = re.compile("Package:\s+%s\nVersion:(.*)" % name)

+             log.info("Package found in : %s", url)

+             versionmotif = re.compile(r"Package:\s+%s\nVersion:(.*)" % name)

              version = versionmotif.search(content).group(1).strip()

              return (version)

          else:

-             log.info("Not Found: %s in %s" % (name, url))

-     except IOError, ex:

-         print 'Could not contact the repository at url: %s' % url

-         log.debug('Error: %s' % ex)

+             log.info("Not Found: %s in %s", name, url)

+     except IOError as ex:

+         print('Could not contact the repository at url: %s' % url)

+         log.debug('Error: %s', ex)

      return None

  

  
@@ -68,7 +73,7 @@ 

      def __init__(self, name=None, url=None, source0=None):

          """ Constructor. """

          self.name = name

-         parser = ConfigParser.ConfigParser()

+         parser = configparser.RawConfigParser()

          parser.read('/etc/R2spec/repos.cfg')

          self.config = parser

          self.log = get_logger()
@@ -84,11 +89,19 @@ 

      def determine_arch(self):

          """ Determine if the package is arch or noarch by looking at the

          sources.

-         Set arch to True if the package is arch dependant.

+         Set arch to True if the package is arch dependent.

          Set arch to False if the package is noarch.

          Let arch to None if could not determine.

          """

-         self.log.info('Determining if the package is arch dependant or not')

+         self.log.info('Determining if the package is arch dependent or not')

+         try:

+             self.arch = self.description['NeedsCompilation'].lower() != 'no'

+         except KeyError:

+             pass

+         else:

+             self.log.info('Package is %sarch dependent',

+                           '' if self.arch else 'not ')

+             return

          extensions = ['c', 'C', 'cp', 'cpp', 'h', 'H',]

          if os.path.exists(self.name):

              for root, dirs, files in os.walk(self.name):
@@ -99,10 +112,10 @@ 

                                  or 'f' in extension \

                                  or 'F' in extension:

                              self.arch = True

-                             self.log.info('Package is arch dependant')

+                             self.log.info('Package is arch dependent')

                              return

              self.arch = False

-             self.log.info('Package is not arch dependant')

+             self.log.info('Package is not arch dependent')

              return

          else:

              self.log.info(
@@ -129,26 +142,35 @@ 

              return

  

          url = self.source0.rsplit('/', 1)[0]

-         url = '%s/%s' % (url,self.source)

-         self.log.info('Downloading %s' % url)

+         url = '%s/%s' % (url, self.source)

+         self.log.info('Downloading %s', url)

  

-         remotefile = urllib2.urlopen(url)

-         localfile = open(sources, 'w')

-         localfile.write(remotefile.read())

-         localfile.close()

+         remotefile = urllib_request.urlopen(url)

+         with open(sources, 'wb') as localfile:

+             localfile.write(remotefile.read())

  

-     def extract_sources(self):

-         """ Extract the sources into the current directory. """

+     def open_sources(self):

+         """ Open the source tarball. """

          sourcedir = get_rpm_tag('_sourcedir')

          tarball = "%s/%s" % (sourcedir, self.source)

-         self.log.info("Opening: %s" % tarball)

+         self.log.info("Opening: %s", tarball)

          try:

-             tar = tarfile.open(tarball)

-             tar.extractall()

-             tar.close()

-         except TarError, err:

+             return tarfile.open(tarball)

+         except tarfile.TarError as err:

              self.log.debug("Error while extracting the tarball")

-             self.log.debug("ERROR: %s" % err)

+             self.log.debug("ERROR: %s", err)

+ 

+     def extract_sources(self):

+         """ Extract the sources into the current directory. """

+         tar = self.open_sources()

+         if tar is None:

+             return

+         try:

+             with tar:

+                 tar.extractall()

+         except tarfile.TarError as err:

+             self.log.debug("Error while extracting the tarball")

+             self.log.debug("ERROR: %s", err)

  

      def get(self, key):

          """ Retrieve the given key from the description information known
@@ -158,7 +180,7 @@ 

          :arg key, the key to retrieve from the DESCRIPTION file of the R

          package

          """

-         if key and key in self.description.keys():

+         if key and key in self.description:

              return self.description[key]

          else:

              return ''
@@ -168,51 +190,58 @@ 

          from in them.

          """

          description = '%s/DESCRIPTION' % self.name

-         self.log.info('Loading "%s"' % description)

+         content = None

          if os.path.exists(self.name) and os.path.isfile(description):

+             self.log.info('Loading "%s" from extracted sources', description)

              try:

-                 stream = open(description, 'r')

-                 content = stream.read()

-                 stream.close()

-             except IOError, err:

+                 with open(description, 'rb') as stream:

+                     content = stream.read()

+             except IOError as err:

                  self.log.info(

-                 'An error occured while reading the DESCRIPTION file: %s' \

-                 % description)

-                 self.log.debug('ERROR: %s' % err)

-             key = None

-             for row in content.split('\n'):

-                 if row.strip():

-                     pattern = re.compile("\w:*")

-                     if pattern.match(row):

-                         key, value = row.split(':', 1)

-                         self.description[key.strip()] = value.strip()

-                     else:

-                         self.description[key] = self.description[key] + ' ' + \

-                             row.strip()

+                     'An error occurred while reading the DESCRIPTION file: %s',

+                     description)

+                 self.log.debug('ERROR: %s', err)

+         else:

+             self.log.info('Loading "%s" from tarball', description)

+             tar = self.open_sources()

+             if tar is not None:

+                 try:

+                     with tar:

+                         with tar.extractfile(description) as stream:

+                             content = stream.read()

+                 except tarfile.TarError as err:

+                     self.log.debug("Error while extracting the DESCRIPTION "

+                                    "file from the tarball")

+                     self.log.debug("ERROR: %s", err)

+             else:

+                 self.log.info('Could not find a DESCRIPTION file "%s" to read',

+                               description)

+                 return

+ 

+         encoding = re.search(b'^Encoding: (.+)$', content, re.MULTILINE)

+         if encoding is not None:

+             content = content.decode(encoding.group(1).decode().strip())

          else:

-             self.log.info('Could not find a DESCRIPTION file "%s" to read' \

-                 % description)

+             content = content.decode('ascii')

+         key = None

+         for row in content.split('\n'):

+             if row.strip():

+                 pattern = re.compile(r"\w:*")

+                 if pattern.match(row):

+                     key, value = row.split(':', 1)

+                     self.description[key.strip()] = value.strip()

+                 else:

+                     self.description[key] = self.description[key] + ' ' + \

+                         row.strip()

  

      def read_config(self):

          """ Read the general configuration containing the repo information

          """

-         parser = ConfigParser.ConfigParser()

+         parser = configparser.RawConfigParser()

          configfile = '/etc/R2spec/config'

          parser.read(configfile)

          self.config = parser

  

-     def remove_sources(self):

-         """ Remove the source we extracted in the current working

-         directory.

-         """

-         self.log.info('Removing extracted sources: "%s"' % self.name)

-         try:

-             shutil.rmtree(self.name)

-         except (IOError, OSError), err:

-             self.log.info('Could not remove the extracted sources: "%s"'\

-                 % self.name)

-             self.log.debug('ERROR: %s' % err)

- 

      def search_package_in_repo(self):

          """ Search a package in all R repositories listed in the general

          configuration file.
@@ -228,8 +257,8 @@ 

                      break

          if version is None:

              self.log.info(

-             'Could not find package "%s" in any of the congifure repos' \

-             % self.name)

+                 'Could not find package "%s" in any of the configured repos',

+                 self.name)

              raise R2specError(

              'Could not find package "%s" in any of the configured repos' \

                  % self.name)
@@ -237,9 +266,7 @@ 

          self.down_version = version.replace('-', '.')

          self.url = self.config.get(repo, 'url')

          self.source0 = self.config.get(repo, 'source')

-         if self.up_version != self.down_version:

-             self.source0 = self.source0.replace('%{version}', self.up_version)

-         self.source = '%s_%s.tar.gz' % (self.name,self.up_version)

+         self.source = '%s_%s.tar.gz' % (self.name, self.up_version)

  

      def set_repo(self, reponame):

          """ This function find the URL and Source0 tag for the spec file
@@ -249,7 +276,6 @@ 

          """

          for section in self.config.sections():

              if section == 'repo:%s' % reponame:

-                 """ Not sure why this format is getting filled out..."""

-                 self.url = self.config.get(section, 'url' % (self.name))

+                 self.url = self.config.get(section, 'url')

                  self.source0 = self.config.get(section, 'source')

                  break

file modified
+55 -59
@@ -20,63 +20,61 @@ 

  Spec class, handles the read/write of the spec file

  """

  

+ from __future__ import absolute_import, division, print_function

  

  import datetime

  import os

- import re

  import sys

- from jinja2 import Template

+ import textwrap

+ from collections import namedtuple

+ 

+ from jinja2 import Environment, FileSystemLoader

  from r2spec import get_logger, get_rpm_tag, R2specError

  

  

- def format_description(description):

-     """ Format the description as required by rpm """

-     step = 75

-     cnt = 0

-     out = []

-     char = 0

-     while cnt < len(description) and char < description.rfind(" "):

-         if len(description[cnt:]) >= step:

-             char = description[cnt: cnt + step].rfind(" ") + cnt

-             out.append(description[cnt: char])

-             cnt = char + 1

+ class Package(namedtuple('Package', 'name version')):

+     def __str__(self):

+         if self.version:

+             return self.name + ' ' + self.version

          else:

-             out.append(description[cnt:])

-             cnt += len(description[cnt:])

+             return self.name

  

-     return "\n".join(out)

+     @property

+     def rpm_version(self):

+         if self.version:

+             return self.name + ' ' + self.version.replace('-', '.')

+         else:

+             return self.name

  

  

  def format_dependencies(dependencies):

      """ Format the dependencies cleanning them as much as possible for rpm.

      """

      ignorelist = ['R']

-     # Regular expression used to determine whether the string is a

-     # version number

-     versionmotif = re.compile('\d\.\d\.?\d?')

      char = {

              '\r': '',

              '(': ' ',

              ')': ' ',

-             ',': ' ',

              '  ': ' ',

              }

  

-     for key in char.keys():

+     for key in char:

          dependencies = dependencies.replace(key, char[key])

      dep_list = []

  

-     for dep in dependencies.split(' '):

-         if dep.strip():

-             if  not ">" in dep \

-             and not "<" in dep \

-             and not "=" in dep \

-             and len(versionmotif.findall(dep)) == 0 \

-             and dep.strip() not in ignorelist:

-                 dep = 'R-%s' % dep.strip()

-                 dep_list.append(dep)

+     for dep in dependencies.split(','):

+         dep = dep.strip()

+         if dep:

+             if ' ' in dep:

+                 name, version = dep.split(' ', 1)

+             else:

+                 name = dep

+                 version = ''

+             if name not in ignorelist:

+                 name = 'R-%s' % name.strip()

+                 dep_list.append(Package(name, version.strip()))

  

-     return ' '.join(dep_list).strip()

+     return dep_list

  

  

  class Spec:
@@ -86,16 +84,17 @@ 

      """

  

      def __init__(self, settings, package=None, no_check=False,

-         no_suggest=False):

+                  with_deps=False):

          """ Constructor.

          """

          self.package = package

          self.settings = settings

-         self.__dict = {}

+         self.__dict = {

+             'with_deps': with_deps

+         }

          self.log = get_logger()

          self.spec = None

          self.no_check = no_check

-         self.no_suggest = no_suggest

  

      def add_files(self, files):

          """ Add to a spec file the given files list.
@@ -151,6 +150,7 @@ 

          """ Fills the different variable required for the spec file. """

          self.log.info('Filling spec variable from info collected')

          self.__dict['packname'] = self.package.name

+         self.__dict['packver'] = self.package.up_version

          self.__dict['arch'] = self.package.arch

          self.__dict['version'] = self.package.down_version

          self.__dict['summary'] = self.package.get('Title')
@@ -161,13 +161,11 @@ 

              self.package.get('Depends'))

          self.__dict['imports'] = format_dependencies(

              self.package.get('Imports'))

-         if not self.no_suggest:

-             self.__dict['suggests'] = format_dependencies(

-                 self.package.get('Suggests'))

-         else:

-             self.__dict['suggests'] = ""

-         self.__dict['description'] = format_description(

-             self.package.get('Description'))

+         self.__dict['suggests'] = format_dependencies(

+             self.package.get('Suggests'))

+         self.__dict['description'] = textwrap.fill(

+             self.package.get('Description'),

+             width=75)

          self.__dict['date'] = datetime.datetime.now(

              ).strftime("%a %b %d %Y")

          self.__dict['name'] = self.settings.get('packager')
@@ -222,17 +220,15 @@ 

          """ Read the empty template and fills it with the information

          retrieved.

          """

-         template = '%s/specfile.tpl' % os.path.dirname(__file__)

          self.log.info('Filling spec template')

+         loader = FileSystemLoader(os.path.dirname(__file__))

+         env = Environment(loader=loader, lstrip_blocks=True, trim_blocks=True)

          try:

-             stream = open(template, 'r')

-             tplfile = stream.read()

-             stream.close()

-             mytemplate = Template(tplfile)

+             mytemplate = env.get_template('specfile.tpl')

              self.spec = mytemplate.render(self.__dict)

-         except IOError, err:

-             self.log.debug('ERROR: %s' % err)

-             raise R2specError('Cannot read the file %s' % template)

+         except IOError as err:

+             self.log.debug('ERROR: %s', err)

+             raise R2specError('Cannot read the file %s' % (err, ))

  

      def get_specfile(self):

          """ Return the path to the spec file.
@@ -246,27 +242,27 @@ 

          """

          specfile = self.get_specfile()

          if os.path.exists(specfile) and os.path.isfile(specfile):

-             self.log.info('Reading file %s' % specfile)

+             self.log.info('Reading file %s', specfile)

              try:

                  stream = open(specfile, 'r')

                  self.spec = stream.read()

                  stream.close()

-             except IOError, err:

-                 self.log.info('Cannot read the file %s' % specfile)

-                 self.log.debug('ERROR: %s' % err)

+             except IOError as err:

+                 self.log.info('Cannot read the file %s', specfile)

+                 self.log.debug('ERROR: %s', err)

  

      def write_spec(self, verbose=False):

          """ Write down the spec to the spec directory as returned by rpm.

          """

          specfile = self.get_specfile()

-         self.log.info('Writing file %s' % specfile)

+         self.log.info('Writing file %s', specfile)

          try:

              stream = open(specfile, 'w')

              stream.write(self.spec)

              stream.close()

-             self.log.debug('Spec file writen: %s' % specfile)

+             self.log.debug('Spec file written: %s', specfile)

              if verbose:

-                 print 'Spec file writen: %s' % specfile

-         except IOError, err:

-             self.log.info('Cannot write the file %s' % specfile)

-             self.log.debug('ERROR: %s' % err)

+                 print('Spec file written: %s' % specfile)

+         except IOError as err:

+             self.log.info('Cannot write the file %s', specfile)

+             self.log.debug('ERROR: %s', err)

file modified
+38 -22
@@ -1,6 +1,9 @@ 

- %global packname  {{ packname }}

- {% if (arch == False) %}%global rlibdir  %{_datadir}/R/library

- {% else %}%global rlibdir  %{_libdir}/R/library

+ %global packname {{ packname }}

+ %global packver  {{ packver }}

+ {% if arch %}

+ %global rlibdir  %{_libdir}/R/library

+ {% else %}

+ %global rlibdir  %{_datadir}/R/library

  {% endif %}

  

  Name:             R-%{packname}
@@ -8,52 +11,65 @@ 

  Release:          1%{?dist}

  Summary:          {{summary}}

  

- Group:            Applications/Engineering 

  License:          {{license}}

  URL:              {{URL}}

  Source0:          {{source0}}

- BuildRoot:        %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

  

  # Here's the R view of the dependencies world:

- # Depends:   {{depends}}

- # Imports:   {{imports}}

- # Suggests:  {{suggests}}

+ # Depends:   {{ depends | join(', ') }}

+ # Imports:   {{ imports | join(', ') }}

+ # Suggests:  {{ suggests | join(', ') }}

  # LinkingTo:

  # Enhances:

  

- {% if (arch == False) %}BuildArch:        noarch

+ {% if not arch %}

+ BuildArch:        noarch

+ {% if with_deps %}

  Requires:         R-core

  {% endif %}

- {% if depends != "" %}Requires:         {{depends}} {% endif %}

- {% if imports != "" %}Requires:         {{imports}} {% endif %}

- {% if suggests != "" %}Requires:         {{suggests}} {% endif %}

- BuildRequires:    R-devel tex(latex) {{depends}}

- {% if imports != "" %}BuildRequires:    {{imports}} {% endif %}

- {% if suggests != "" %}BuildRequires:   {{suggests}} {% endif %}

+ {% endif %}

+ {% if with_deps %}

+ {% for dep in depends + imports %}

+ Requires:         {{dep.rpm_version}}

+ {% endfor %}

+ {% for dep in suggests %}

+ Suggests:         {{dep.rpm_version}}

+ {% endfor %}

+ {% endif %}

+ BuildRequires:    R-devel

+ BuildRequires:    tex(latex)

+ {% for dep in depends + imports %}

+ BuildRequires:    {{dep.rpm_version}}

+ {% endfor %}

+ {% for dep in suggests %}

+ BuildRequires:    {{dep.rpm_version}}

+ {% endfor %}

  

  %description

  {{description}}

  

+ 

  %prep

  %setup -q -c -n %{packname}

  

+ 

  %build

  

+ 

  %install

- rm -rf %{buildroot}

  mkdir -p %{buildroot}%{rlibdir}

  %{_bindir}/R CMD INSTALL -l %{buildroot}%{rlibdir} %{packname}

  test -d %{packname}/src && (cd %{packname}/src; rm -f *.o *.so)

  rm -f %{buildroot}%{rlibdir}/R.css

- {% if (no_check == False) %}

+ 

+ 

+ {% if not no_check %}

  %check

  %{_bindir}/R CMD check %{packname}

- {% endif %}

- %clean

- rm -rf %{buildroot}

  

+ 

+ {% endif %}

  %files

- %defattr(-, root, root, -)

  %dir %{rlibdir}/%{packname}

  %doc %{rlibdir}/%{packname}/doc

  %doc %{rlibdir}/%{packname}/html
@@ -67,5 +83,5 @@ 

  

  

  %changelog

- * {{date}} {{name}} <{{email}}> {{version}}-1

+ * {{date}} {{name}} <{{email}}> - {{version}}-1

  - initial package for Fedora

file modified
+10 -10
@@ -4,22 +4,22 @@ 

  package = http://cran.r-project.org/src/contrib/PACKAGES

  

  [repo:bioconductor]

- url = http://bioconductor.org/packages/release/bioc/html/%{packname}.html

- source = http://bioconductor.org/packages/release/bioc/src/contrib/%{packname}_%{version}.tar.gz

- package = http://bioconductor.org/packages/release/bioc/src/contrib/PACKAGES

+ url = https://bioconductor.org/packages/release/bioc/html/%{packname}.html

+ source = https://bioconductor.org/packages/release/bioc/src/contrib/%{packname}_%{packver}.tar.gz

+ package = https://bioconductor.org/packages/release/bioc/src/contrib/PACKAGES

  

  [repo:bioconductor-annotation]

- url = http://bioconductor.org/packages/release/data/annotation/html/%{packname}.html

- source = http://bioconductor.org/packages/release/data/annotation/src/contrib/%{packname}_%{version}.tar.gz

- package = http://bioconductor.org/packages/release/data/annotation/src/contrib/PACKAGES

+ url = https://bioconductor.org/packages/release/data/annotation/html/%{packname}.html

+ source = https://bioconductor.org/packages/release/data/annotation/src/contrib/%{packname}_%{packver}.tar.gz

+ package = https://bioconductor.org/packages/release/data/annotation/src/contrib/PACKAGES

  

  [repo:bioconductor-experiment]

- url = http://bioconductor.org/packages/release/data/experiment/html/%{packname}.html

- source = http://bioconductor.org/packages/release/data/experiment/src/contrib/%{packname}_%{version}.tar.gz

- package = http://bioconductor.org/packages/release/data/experiment/src/contrib/PACKAGES

+ url = https://bioconductor.org/packages/release/data/experiment/html/%{packname}.html

+ source = https://bioconductor.org/packages/release/data/experiment/src/contrib/%{packname}_%{packver}.tar.gz

+ package = https://bioconductor.org/packages/release/data/experiment/src/contrib/PACKAGES

  

  [repo:r-forge]

  url = https://r-forge.r-project.org/projects/%{packname}/index.html

- source = https://r-forge.r-project.org/src/contrib/%{packname}_%{version}.tar.gz

+ source = https://r-forge.r-project.org/src/contrib/%{packname}_%{packver}.tar.gz

  package = https://r-forge.r-project.org/src/contrib/PACKAGES

  

file modified
+6 -3
@@ -3,7 +3,9 @@ 

  Setup script

  """

  

- from distutils.core import setup

+ from __future__ import absolute_import, division, print_function

+ 

+ from setuptools import setup

  from r2spec import VERSION

  

  setup(
@@ -18,9 +20,10 @@ 

      maintainer = 'Pierre-Yves Chibon',

      maintainer_email = 'pingou@pingoured.fr',

      license = 'GPLv3+',

-     download_url = 'https://fedorahosted.org/releases/r/2/r2spec/',

-     url = 'https://fedorahosted.org/r2spec/',

+     download_url='https://pagure.io/r2spec/releases',

+     url='https://pagure.io/r2spec',

      package_dir = {'R2spec': 'r2spec'},

      packages = ['r2spec'],

+     include_package_data=True,

      scripts=['R2spec', 'R2rpm'],

      )

file modified
+10 -6
@@ -19,6 +19,7 @@ 

  

  """ R2rpm tests script """

  

+ from __future__ import absolute_import, division, print_function

  

  # Cases:

  # -p <package>
@@ -41,7 +42,11 @@ 

  import shutil

  import sys

  import unittest

- import urllib2

+ 

+ try:

+     import urllib.request as urllib_request

+ except ImportError:

+     import urllib2 as urllib_request

  

  sys.path.insert(0, os.path.abspath('../'))

  from r2spec.r2spec_obj import R2rpm, setup_parser
@@ -67,10 +72,9 @@ 

      :arg url, url to the object to download

      """

      sources = url.rsplit('/', 1)[1]

-     remotefile = urllib2.urlopen(url)

-     localfile = open(sources, 'w')

-     localfile.write(remotefile.read())

-     localfile.close()

+     remotefile = urllib_request.urlopen(url)

+     with open(sources, 'wb') as localfile:

+         localfile.write(remotefile.read())

      return sources

  

  
@@ -95,7 +99,7 @@ 

          arg = parser.parse_args()

          try:

              R2rpm().main(arg)

-         except R2specError, err:

+         except R2specError as err:

              self.assertEqual('Not enough argument given, see -h/--help',

                  err.value)

  

file modified
+10 -6
@@ -19,6 +19,7 @@ 

  

  """ R2spec tests script """

  

+ from __future__ import absolute_import, division, print_function

  

  # Cases:

  # -p <package>
@@ -42,7 +43,11 @@ 

  import shutil

  import sys

  import unittest

- import urllib2

+ 

+ try:

+     import urllib.request as urllib_request

+ except ImportError:

+     import urllib2 as urllib_request

  

  sys.path.insert(0, os.path.abspath('../'))

  from r2spec.r2spec_obj import R2spec, setup_parser
@@ -68,10 +73,9 @@ 

      :arg url, url to the object to download

      """

      sources = url.rsplit('/', 1)[1]

-     remotefile = urllib2.urlopen(url)

-     localfile = open(sources, 'w')

-     localfile.write(remotefile.read())

-     localfile.close()

+     remotefile = urllib_request.urlopen(url)

+     with open(sources, 'wb') as localfile:

+         localfile.write(remotefile.read())

      return sources

  

  
@@ -96,7 +100,7 @@ 

          arg = parser.parse_args()

          try:

              R2spec().main(arg)

-         except R2specError, err:

+         except R2specError as err:

              self.assertEqual('Not enough argument given, see -h/--help',

                  err.value)

  

file modified
+2
@@ -19,6 +19,8 @@ 

  

  """ R2spec launcher script """

  

+ from __future__ import absolute_import, division, print_function

+ 

  import unittest

  from test.test_R2spec import R2spectests

  from test.test_R2rpm import R2rpmtests

  • Added --no-check and --no-suggest to man pages
    ( and use these options instead of changes in template)
  • Added openSUSE spec and template (just to have them, may be there are better way to support openSUSE)
  • use NeedCompilation and if so add compilers to BuildRequires
  • Added rpm-build to R2Spec.spec (for now only for openSUSE) to the Requires.
  • R2rpm now includes the package directory in the filelist (finally package abe builds in OBS with an automatically generated spec!)
  • sequence of repo checks changed. CRAN is most important, at least as default.

1 new commit added

  • incorporated stuff from
5 years ago

1 new commit added

  • magic line to set python_sitelib no longer needed
5 years ago

This needs rebasing, since some of it has been implemented.

rebased onto 69c4d95

4 years ago