Отсутствует ключ словаря Python - PullRequest
1 голос
/ 05 июня 2010

Я подумал, что соберу быстрый скрипт для консолидации правил CSS, которые я распределил по нескольким файлам CSS, и тогда я могу его минимизировать.

Я новичок в Python, но подумал, что было бы неплохо попробовать новый язык. Мой основной цикл не разбирает CSS так, как я думал.

Я заполняю список селекторами, проанализированными из файлов CSS, чтобы вернуть правила CSS по порядку. Далее в скрипте список содержит элемент, который не найден в словаре.

    for line in self.file.readlines():
      if self.hasSelector(line):
        selector = self.getSelector(line)
        if selector not in self.order:
          self.order.append(selector)
      elif selector and self.hasProperty(line):
        # rules.setdefault(selector,[]).append(self.getProperty(line))
        property = self.getProperty(line)
        properties = [] if selector not in rules else rules[selector]
        if property not in properties:
          properties.append(property)
        rules[selector] = properties
        # print "%s :: %s" % (selector, "".join(rules[selector]))
    return rules

Произошла ошибка:

$ css-combine combined.css test1.css test2.css 
Traceback (most recent call last):
  File "css-combine", line 108, in <module>
    c.run(outfile, stylesheets)
  File "css-combine", line 64, in run
    [(selector, rules[selector]) for selector in parser.order],
KeyError: 'p'

Поменяйте местами входы:

$ css-combine combined.css test2.css test1.css 
Traceback (most recent call last):
  File "css-combine", line 108, in <module>
    c.run(outfile, stylesheets)
  File "css-combine", line 64, in run
    [(selector, rules[selector]) for selector in parser.order],
KeyError: '#header_.title'

Я сделал несколько странных вещей в коде, таких как подпространства для подчеркиваний в именах ключей словаря на случай, если это было проблемой - может быть, это мягкая предосторожность? В зависимости от порядка ввода, в словаре не может быть найден другой ключ.

Сценарий:

#!/usr/bin/env python

import optparse
import re

class CssParser:

  def __init__(self):
    self.file = False
    self.order = [] # store rules assignment order

  def parse(self, rules = {}):
    if self.file == False:
      raise IOError("No file to parse")

    selector = False
    for line in self.file.readlines():
      if self.hasSelector(line):
        selector = self.getSelector(line)
        if selector not in self.order:
          self.order.append(selector)
      elif selector and self.hasProperty(line):
        # rules.setdefault(selector,[]).append(self.getProperty(line))
        property = self.getProperty(line)
        properties = [] if selector not in rules else rules[selector]
        if property not in properties:
          properties.append(property)
        rules[selector] = properties
        # print "%s :: %s" % (selector, "".join(rules[selector]))
    return rules

  def hasSelector(self, line):
    return True if re.search("^([#a-z,\.:\s]+){", line) else False

  def getSelector(self, line):
    s = re.search("^([#a-z,:\.\s]+){", line).group(1)
    return "_".join(s.strip().split())

  def hasProperty(self, line):
    return True if re.search("^\s?[a-z-]+:[^;]+;", line) else False

  def getProperty(self, line):
    return re.search("([a-z-]+:[^;]+;)", line).group(1)


class Consolidator:
  """Class to consolidate CSS rule attributes"""

  def run(self, outfile, files):
    parser = CssParser()
    rules = {}
    for file in files:
      try:
        parser.file = open(file)
        rules = parser.parse(rules)
      except IOError:
        print "Cannot read file: " + file
      finally:
        parser.file.close()

    self.serialize(
      [(selector, rules[selector]) for selector in parser.order],
      outfile
    )

  def serialize(self, rules, outfile):
    try:
      f = open(outfile, "w")
      for rule in rules:
        f.write(
          "%s {\n\t%s\n}\n\n" % (
            " ".join(rule[0].split("_")), "\n\t".join(rule[1])
          )
        )
    except IOError:
      print "Cannot write output to: " + outfile
    finally:
      f.close()

def init():
  op = optparse.OptionParser(
    usage="Usage: %prog [options] <output file> <stylesheet1> " +
      "<stylesheet2> ... <stylesheetN>",
    description="Combine CSS rules spread across multiple " +
      "stylesheets into a single file"
  )
  opts, args = op.parse_args()
  if len(args) < 3:
    if len(args) == 1:
      print "Error: No input files specified.\n"
    elif len(args) == 2:
      print "Error: One input file specified, nothing to combine.\n"
    op.print_help();
    exit(-1)

  return [opts, args]

if __name__ == '__main__':
  opts, args = init()
  outfile, stylesheets = [args[0], args[1:]]
  c = Consolidator()
  c.run(outfile, stylesheets)

Тест файла CSS 1:

body {
    background-color: #e7e7e7;
}

p {
    margin: 1em 0em;    
}

Файл 2:

body {
    font-size: 16px;
}

#header .title {
    font-family: Tahoma, Geneva, sans-serif;
    font-size: 1.9em;
}

#header .title a, #header .title a:hover {
    color: #f5f5f5;
    border-bottom: none;
    text-shadow: 2px 2px 3px rgba(0, 0, 0, 1);
}

Заранее спасибо.

1 Ответ

3 голосов
/ 05 июня 2010

Изменение

def hasProperty(self, line):
    return True if re.search("^\s?[a-z-]+:[^;]+;", line) else False

до

def hasProperty(self, line):
    return True if re.search("^\s*[a-z-]+:[^;]+;", line) else False

hasProperty не соответствует никому, потому что \s? соответствует только 0 или 1 пробелу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...