code: def parse_specification(spec):
      
      name, extras, const = spec, [], ''
  
      # Remove excess whitespace
      spec = ' '.join(p for p in spec.split(' ') if p).strip()
  
      # Extract marker (Assumes that there can only be one ';' inside the spec)
      spec, marker = split_spec(spec, ';')
  
      # Extract url (Assumes that there can only be one '@' inside the spec)
      spec, url = split_spec(spec, '@')
  
      # Find name, extras and constraints
      r = PARTIAL_PYPI_SPEC_PATTERN.match(spec)
      if r:
          # Normalize name
          name = r.group('name')
  
          # Clean extras
          extras = r.group('extras')
          extras = [e.strip() for e in extras.split(',') if e] if extras else []
  
          # Clean constraints
          const = r.group('constraints')
          const = ''.join(c for c in const.split(' ') if c).strip()
          if const.startswith('(') and const.endswith(')'):
              # Remove parens
              const = const[1:-1]
  
      return name, extras, const, marker, url
docs: Parse a requirement from a python distribution metadata and return a
      tuple with name, extras, constraints, marker and url components.
  
      This method does not enforce strict specifications but extracts the
      information which is assumed to be *correct*. As such no errors are raised.
  
      Example
      -------
      spec = 'requests[security, tests] >=3.3.0 ; foo >= 2.7 or bar == 1'
  
      ('requests', ['security', 'pyfoo'], '>=3.3.0', 'foo >= 2.7 or bar == 1', '')