def test_at_media(self): for (css_source, expected_rules, expected_errors) in [ (' /* hey */\n', [], []), ('@media {}', [(['all'], [])], []), ('@media all {}', [(['all'], [])], []), ('@media screen, print {}', [(['screen', 'print'], [])], []), ('@media all;', [], ['invalid @media rule: missing block']), ('@media 4 {}', [], ['expected a media type, got INTEGER']), ('@media , screen {}', [], ['expected a media type']), ('@media screen, {}', [], ['expected a media type']), ('@media screen print {}', [], ['expected a media type, got IDENT, IDENT']), ('@media all { @page { a: 1 } @media; @import; foo { a: 1 } }', [(['all'], [('foo', [('a', [('INTEGER', 1)])])])], [ '@page rule not allowed in @media', '@media rule not allowed in @media', '@import rule not allowed in @media' ]), ]: stylesheet = CSS21Parser().parse_stylesheet(css_source) self.assert_errors(stylesheet.errors, expected_errors) for rule in stylesheet.rules: self.ae(rule.at_keyword, '@media') result = [(rule.media, [(sub_rule.selector.as_css(), [ (decl.name, list(jsonify(decl.value))) for decl in sub_rule.declarations ]) for sub_rule in rule.rules]) for rule in stylesheet.rules] self.ae(result, expected_rules)
def test_images(self): f_mapcss = open(self.filename) css = f_mapcss.read() f_mapcss.close() stylesheet = CSS21Parser().parse_stylesheet(css) img_urls = [] z = ZipFile(self.zipfile, 'r') for rule in stylesheet.rules: for declaration in rule.declarations: if declaration.name == 'icon-image': if str( declaration.value[0].value ).startswith('http://') or str( declaration.value[0].value).startswith('https://'): img_urls.append(declaration.value[0].value) else: try: t = z.read(declaration.value[0].value) except Exception: print 'error opening:{}'.format( declaration.value[0].value) if len(t) == 0: print 'file is empty:{}'.format( declaration.value[0].value) self.assertTrue(len(t) != 0) rs = (grequests.get(u) for u in img_urls) responses = grequests.map(rs) for response in responses: if response.status_code != 200: print 'url not found:{}'.format(response.url) self.assertTrue(response.status_code == 200) self.assertTrue(len(responses) == len(img_urls))
def test_important(self): for (css_source, expected_declarations, expected_errors) in [ (' /* hey */\n', [], []), ('a:1; b:2', [('a', [('INTEGER', 1)], None), ('b', [('INTEGER', 2)], None)], []), ('a:1 important; b: important', [('a', [('INTEGER', 1), ('S', ' '), ('IDENT', 'important')], None), ('b', [('IDENT', 'important')], None)], []), ('a:1 !important; b:2', [('a', [('INTEGER', 1)], 'important'), ('b', [('INTEGER', 2)], None)], []), ('a:1!\t Im\\50 O\\RTant; b:2', [('a', [('INTEGER', 1)], 'important'), ('b', [('INTEGER', 2)], None)], []), ('a: !important; b:2', [('b', [('INTEGER', 2)], None)], ['expected a value before !important']), ]: declarations, errors = CSS21Parser().parse_style_attr(css_source) self.assert_errors(errors, expected_errors) result = [(decl.name, list(jsonify(decl.value)), decl.priority) for decl in declarations] self.ae(result, expected_declarations)
def test_at_import(self): for (css_source, expected_rules, expected_errors) in [ (' /* hey */\n', [], []), ('@import "foo.css";', [('foo.css', ['all'])], []), ('@import url(foo.css);', [('foo.css', ['all'])], []), ('@import "foo.css" screen, print;', [('foo.css', ['screen', 'print'])], []), ('@charset "ascii"; @import "foo.css"; @import "bar.css";', [('foo.css', ['all']), ('bar.css', ['all'])], []), ('foo {} @import "foo.css";', [], ['@import rule not allowed after a ruleset']), ('@page {} @import "foo.css";', [], ['@import rule not allowed after an @page rule']), ('@import ;', [], ['expected URI or STRING for @import rule']), ('@import foo.css;', [], ['expected URI or STRING for @import rule, got IDENT']), ('@import "foo.css" {}', [], ["expected ';', got a block"]), ]: # Pass 'encoding' to allow @charset stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') self.assert_errors(stylesheet.errors, expected_errors) result = [(rule.uri, rule.media) for rule in stylesheet.rules if rule.at_keyword == '@import'] self.ae(result, expected_rules)
def test_parse_style_attr(self): for (css_source, expected_declarations, expected_errors) in [ (' /* hey */\n', [], []), ('b:4', [('b', [('INTEGER', 4)])], []), ('{b:4}', [], ['expected a property name, got {']), ('b:4} c:3', [], ['unmatched } token in property value']), (' 4px; bar: 12% ', [('bar', [('PERCENTAGE', 12)])], ['expected a property name, got DIMENSION']), ('bar! 3cm auto ; baz: 7px', [('baz', [('DIMENSION', 7)])], ["expected ':', got DELIM"]), ('foo; bar ; baz: {("}"/* comment */) {0@fizz}}', [('baz', [ ('{', [('(', [('STRING', '}')]), ('S', ' '), ('{', [('INTEGER', 0), ('ATKEYWORD', '@fizz')])]) ])], ["expected ':'", "expected ':'"]), ('bar: ; baz: not(z)', [ ('baz', [('FUNCTION', 'not', [('IDENT', 'z')])]) ], ['expected a property value']), ('bar: (]) ; baz: U+20', [('baz', [('UNICODE-RANGE', 'U+20')])], ['unmatched ] token in (']), ]: declarations, errors = CSS21Parser().parse_style_attr(css_source) self.assert_errors(errors, expected_errors) result = [(decl.name, list(jsonify(decl.value))) for decl in declarations] self.ae(result, expected_declarations)
def test_at_import(css_source, expected_rules, expected_errors): # Pass 'encoding' to allow @charset stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') assert_errors(stylesheet.errors, expected_errors) result = [(rule.uri, rule.media) for rule in stylesheet.rules if rule.at_keyword == '@import'] assert result == expected_rules
def test_css(self): f_mapcss = open(self.filename) css = f_mapcss.read() f_mapcss.close() stylesheet = CSS21Parser().parse_stylesheet(css) if stylesheet.errors: for error in stylesheet.errors: print error self.assertTrue(len(stylesheet.errors) == 0)
def parse_filename(css_bytes, kwargs): css_file = tempfile.NamedTemporaryFile(delete=False) try: css_file.write(css_bytes) # Windows can not open the filename a second time while # it is still open for writing. css_file.close() return CSS21Parser().parse_stylesheet_file(css_file.name, **kwargs) finally: os.remove(css_file.name)
def test_at_media(css_source, expected_rules, expected_errors): stylesheet = CSS21Parser().parse_stylesheet(css_source) assert_errors(stylesheet.errors, expected_errors) for rule in stylesheet.rules: assert rule.at_keyword == '@media' result = [(rule.media, [(sub_rule.selector.as_css(), [ (decl.name, list(jsonify(decl.value))) for decl in sub_rule.declarations ]) for sub_rule in rule.rules]) for rule in stylesheet.rules] assert result == expected_rules
def test_at_rules(self): for (css_source, expected_rules, expected_errors) in [ (' /* hey */\n', 0, []), ('foo {}', 1, []), ('foo{} @lipsum{} bar{}', 2, ['unknown at-rule in stylesheet context: @lipsum']), ('@charset "ascii"; foo {}', 1, []), (' @charset "ascii"; foo {}', 1, ['mis-placed or malformed @charset rule']), ('@charset ascii; foo {}', 1, ['mis-placed or malformed @charset rule']), ('foo {} @charset "ascii";', 1, ['mis-placed or malformed @charset rule']), ]: # Pass 'encoding' to allow @charset stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') self.assert_errors(stylesheet.errors, expected_errors) self.ae(len(stylesheet.rules), expected_rules)
def test_in_at_media(): css = '@media print { @page { size: A4 } }' stylesheet = CSS21Parser().parse_stylesheet(css) assert_errors(stylesheet.errors, ['@page rule not allowed in @media']) at_media_rule, = stylesheet.rules assert at_media_rule.at_keyword == '@media' assert at_media_rule.rules == [] stylesheet = CSSPage3Parser().parse_stylesheet(css) assert stylesheet.errors == [] at_media_rule, = stylesheet.rules at_page_rule, = at_media_rule.rules assert at_media_rule.at_keyword == '@media' assert at_page_rule.at_keyword == '@page' assert len(at_page_rule.declarations) == 1
def test_at_page(css, expected_result, expected_errors): stylesheet = CSS21Parser().parse_stylesheet(css) assert_errors(stylesheet.errors, expected_errors) if expected_result is None: assert not stylesheet.rules else: assert len(stylesheet.rules) == 1 rule = stylesheet.rules[0] assert rule.at_keyword == '@page' assert rule.at_rules == [] # in CSS 2.1 result = ( rule.selector, rule.specificity, [(decl.name, list(jsonify(decl.value))) for decl in rule.declarations], ) assert result == expected_result
def create_csspropertyset_from_css(cls, css): """ creates a csspropertyset from css-code """ parser = CSS21Parser() stylesheet = None #try: stylesheet = parser.parse_stylesheet_bytes(css) #except Exception,e : # raise e # implement correct error handling propertyset = CSSPropertySet(cls._core) for rule in stylesheet.rules: selector = ",".join([s.as_css() for s in rule.selector]) for declaration in rule.declarations: values = [val.value for val in declaration.value] propertyset.edit_value(selector, declaration.name, ",".join(values)) return propertyset
def _process_images(self, frag, extra_path): for i, img in enumerate( filter( lambda img: img.attrib.get('src') and img.attrib['src']. startswith("data:"), frag.cssselect('img'))): protocol_matcher = _RE_PROTOCOL.match(img.attrib['src']) if not protocol_matcher: logger.debug( "Data protocol found, but was malformed, {0}".format( img.attrib['src'])) continue base, extension = protocol_matcher.group("mime").split("/", 1) if base != "image": continue img_name = img.attrib.get('title', base) + str(i) imgdata = base64.b64decode(protocol_matcher.group("data")) if 'style' in img.attrib and 'width' in img.attrib[ 'style'] and 'height' in img.attrib['style']: style = CSS21Parser().parse_style_attr(img.attrib['style'])[0] style = { dec.name: dec.value[0].value for dec in style if dec.name in ['width', 'height'] } imgproc = Image.open(BytesIO(imgdata)) if imgproc.mode == "P": if len(imgproc.palette.getdata()[1]) > 256: imgproc = imgproc.convert("RGB") imgproc = imgproc.resize((style['width'], style['height']), Image.LANCZOS) params = {} format = extension if format == "jpg" and imgproc.mode not in [ "RGB", "L", "CMYK" ]: format = "png" imgbuffer = BytesIO() imgproc.save(imgbuffer, format=format, **params) imgdata = imgbuffer.getvalue() name = default_storage.save( os.path.join('images', 'aloha-uploads', extra_path, ".".join( (img_name, extension))), ContentFile(imgdata)) img.attrib['src'] = posixpath.join(settings.MEDIA_URL, name) return frag
def test_at_page(self): for (css, expected_result, expected_errors) in [ ('@page {}', (None, (0, 0), []), []), ('@page:first {}', ('first', (1, 0), []), []), ('@page :left{}', ('left', (0, 1), []), []), ('@page\t\n:right {}', ('right', (0, 1), []), []), ('@page :last {}', None, ['invalid @page selector']), ('@page : right {}', None, ['invalid @page selector']), ('@page table:left {}', None, ['invalid @page selector']), ('@page;', None, ['invalid @page rule: missing block']), ('@page { a:1; ; b: 2 }', (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), []), ('@page { a:1; c: ; b: 2 }', (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), ['expected a property value']), ('@page { a:1; @top-left {} b: 2 }', (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), ['unknown at-rule in @page context: @top-left']), ('@page { a:1; @top-left {}; b: 2 }', (None, (0, 0), [('a', [('INTEGER', 1)]), ('b', [('INTEGER', 2)])]), ['unknown at-rule in @page context: @top-left']), ]: stylesheet = CSS21Parser().parse_stylesheet(css) self.assert_errors(stylesheet.errors, expected_errors) if expected_result is None: self.assertFalse(stylesheet.rules) else: self.ae(len(stylesheet.rules), 1) rule = stylesheet.rules[0] self.ae(rule.at_keyword, '@page') self.ae(rule.at_rules, []) # in CSS 2.1 result = ( rule.selector, rule.specificity, [(decl.name, list(jsonify(decl.value))) for decl in rule.declarations], ) self.ae(result, expected_result)
__license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' import numbers from collections import Counter, defaultdict from operator import attrgetter from lxml import etree from calibre.ebooks import parse_css_length from calibre.ebooks.docx.writer.utils import convert_color, int_or_zero from calibre.utils.localization import lang_as_iso639_1 from polyglot.builtins import iteritems, filter, unicode_type from tinycss.css21 import CSS21Parser css_parser = CSS21Parser() border_edges = ('left', 'top', 'right', 'bottom') border_props = ('padding_%s', 'border_%s_width', 'border_%s_style', 'border_%s_color') ignore = object() def parse_css_font_family(raw): decl, errs = css_parser.parse_style_attr('font-family:' + raw) if decl: for token in decl[0].value: if token.type in 'STRING IDENT': val = token.value if val == 'inherit': break
def test_important(css_source, expected_declarations, expected_errors): declarations, errors = CSS21Parser().parse_style_attr(css_source) assert_errors(errors, expected_errors) result = [(decl.name, list(jsonify(decl.value)), decl.priority) for decl in declarations] assert result == expected_declarations
def test_at_rules(css_source, expected_rules, expected_errors): # Pass 'encoding' to allow @charset stylesheet = CSS21Parser().parse_stylesheet(css_source, encoding='utf8') assert_errors(stylesheet.errors, expected_errors) result = len(stylesheet.rules) assert result == expected_rules
def processElement(self, el): elid = el.get('id', "") if elid == "SECTIONINFO": ## process section wide information here for child in el: if stripNamespaceFromTag(child.tag) in ["text", "flowRoot"]: # This is a bit of a hack: # Illustrator does not give paragraphs indicators. # Rather, it arranges text snippets at x,y coordinates. # We infer paragraphs based on snippets starting with "+". # collect snippets from subnodes; separate them by __|__ textfromsvg = ("__|__" + "__|__".join([x for x in child.itertext()])) textfromsvg = textfromsvg.replace("__|__+", "__P__") textfromsvg = textfromsvg.replace("__|__", " ") paragraphs = textfromsvg.split("__P__") # remove unnecessary whitespace paragraphs = [" ".join(par.split()) for par in paragraphs] try: paragraphs.remove("") except ValueError: pass self.sectiondescription = paragraphs elif child.get('id', "").startswith("I"): self.sectioninstructionicon = allChildrenToSVG(child) elif stripNamespaceFromTag(child.tag) == "rect": pass # we don't care, illustrator puts them together with text else: print(("WARNING: UDO (unknown data object ;-)" " in SECTION description element:"), child, child.get('id', "--unknown--")) else: # ignore any elements where the id could not be translated into a key try: key = self.keyFromId(elid) except ValueError: return newitem = {} if self.viewBox: newitem['viewBox'] = self.viewBox for child in el: if child.get('id', "").startswith("t0"): newitem['pre'] = allChildrenToSVG(child) newitem['testDOM'] = allChildrenToSVG(child) elif child.get('id', "").startswith("t1"): newitem['post'] = allChildrenToSVG(child) elif child.get('id', "").startswith("I"): newitem['pre'] += allChildrenToSVG(child) newitem['post'] += allChildrenToSVG(child) newitem['testDOM'] += allChildrenToSVG(child) elif child.get('id', "").startswith("EX"): # Example element collection newitem['pre'] = "<!-- no precondition for this test -->" newitem['post'] = "<!-- no postcondition for this test -->" newitem['testDOM'] = allChildrenToSVG(child) elif child.get('id', "").startswith("BBox"): # BBox overrides viewBox newitem['viewBox'] = (child.get('x', "") + " " + child.get('y', "") + " " + child.get('width', "") + " " + child.get('height', "")) elif stripNamespaceFromTag(child.tag) == "g": print( "WARNING: Encountered invalid sublayer or group %s in test %s." % (child.get('id', "--unknown--"), key)) elif stripNamespaceFromTag(child.tag) in ["text", "flowRoot"]: # text from all subnodes, separated by ' ' descriptionfromsvg = " ".join( [x for x in child.itertext()]) # remove unnecessary whitespace (kills newline etc) descriptionfromsvg = " ".join(descriptionfromsvg.split()) index = descriptionfromsvg.find("META") if index == "-1": newitem['testdescription'] = descriptionfromsvg else: newitem['testdescription'] = descriptionfromsvg[:index] meta = descriptionfromsvg[index:] parsedmeta = CSS21Parser().parse_stylesheet(meta) if len(parsedmeta.errors): print(parsedmeta.errors) try: for decl in parsedmeta.rules[0].declarations: # Remove " ": use meta info in class lists newitem[decl.name] = ( decl.value.as_css().replace(" ", "")) except IndexError: print("Empty META Block") elif stripNamespaceFromTag(child.tag) == "rect": # we don't care for rect (illustrator creates them) pass else: print( "WARNING: UDO (unknown data object ;-) in test element:", child, child.get('id', "--unknown--"), key) newitem['testid'] = key # map True to "fail" and False to "pass" newitem['expectedto'] = { True: "fail", False: "pass" }[key in SCT.expected_to_fail] self.addItem(key, newitem)
def almacenar_clasificacion(self): web = urllib2.urlopen(self.clasificacion) soup = BeautifulSoup(web.read(), 'html.parser') equipos = soup.findAll('td', {'class' : 'txt-al-l'}) complementos = soup.find('th', {'class' : 'txt-al-l'}) busqueda_grupos_estadisticas = soup.findAll('th', class_ = '', colspan = True) busqueda_nom_estadisticas = soup.findAll('th', class_ = '', colspan = False, string = True) busqueda_leyendas = soup.find('ul', class_ = 'leyenda_clasi clasi-comp') tam_grupos = len(busqueda_grupos_estadisticas) tam_estadisticas = len(busqueda_nom_estadisticas)/tam_grupos + 1 tam_datos = int(busqueda_grupos_estadisticas[0]['colspan']) nom_estadisticas = '' if busqueda_leyendas: leyendas = [leyenda.string for leyenda in busqueda_leyendas.children if leyenda != '\n'] else: leyendas = None clasificacion = {} zonas = [] zonas_st = '' busqueda_nom_estadisticas.insert(0, complementos.next_sibling.next_sibling.strong.string) busqueda_nom_estadisticas = busqueda_nom_estadisticas[0:tam_estadisticas] for indice in range(tam_estadisticas): nom_estadisticas += busqueda_nom_estadisticas[indice].string + '-' nom_estadisticas = nom_estadisticas[:-1] for equipo in equipos: zona = equipo.parent.get('class') if zona: zona = zona[0] if 'tr.' + zona not in zonas: zonas.append('tr.' + zona) datos = equipo.parent.findAll('td') posicion = 0 nombre_equipo = '' estadisticas = ['', '', ''] indice_estadisticas = -1 for indice in range(len(datos)): if indice == 0: posicion = datos[indice].next_element.next_element.string nombre_equipo = datos[indice].next_element.next_element.next_sibling.next_sibling['title'].split(':')[0] elif indice % tam_datos == 1: indice_estadisticas += 1 estadisticas[indice_estadisticas] += datos[indice].string else: estadisticas[indice_estadisticas] += ('-' + datos[indice].string) general = [nombre_equipo] general.extend(estadisticas) general.append(zona) clasificacion[posicion] = general if leyendas: css = urllib2.urlopen('http://as01.epimg.net/css/v1.x/v1.2/secciones/resultados_clasificaciones.css') parser = CSS21Parser() style_sheet = CSS21Parser.parse_stylesheet(parser, css.read(), encoding='utf-8') for indice in range(len(zonas)): zona = zonas[indice] leyenda = leyendas[indice] for rule in style_sheet.rules: if zona in rule.selector.as_css(): for declaration in rule.declarations: if 'background' == declaration.name: zonas_st += (zona + ':' + leyenda + ':' + declaration.value.as_css()) break clasificacion[0] = [nom_estadisticas, busqueda_grupos_estadisticas[0].string, busqueda_grupos_estadisticas[1].string, busqueda_grupos_estadisticas[2].string, zonas_st] clasificacion = OrderedDict(sorted(clasificacion.items(), key = lambda t: t[0])) connection = sqlite3.connect(self.bd) connection.text_factory = str connection.execute('''DROP TABLE IF EXISTS C''' + self.tabla) connection.execute('''CREATE TABLE C''' + self.tabla + '''( ID INTEGER PRIMARY KEY AUTOINCREMENT, POSICION TEXT NOT NULL, EQUIPO TEXT NOT NULL, EST_TOTAL TEXT NOT NULL, EST_CASA TEXT NOT NULL, EST_VISITANTE TEXT NOT NULL, ZONA TEXT );''') for posicion in clasificacion.keys(): connection.execute('''INSERT INTO C''' + self.tabla + '''(POSICION, EQUIPO, EST_TOTAL, EST_CASA, EST_VISITANTE, ZONA) VALUES (?, ?, ?, ?, ?, ?);''', (posicion, clasificacion[posicion][0],clasificacion[posicion][1], clasificacion[posicion][2],\ clasificacion[posicion][3], clasificacion[posicion][4])) connection.commit() cursor = connection.execute('SELECT COUNT(*) FROM C' + self.tabla) cursor = cursor.fetchone() connection.close() tkMessageBox.showinfo('BD creada correctamente', 'BD creada correctamente. Hay '+ str(cursor[0]) + ' registros')
def parse_bytesio_file(css_bytes, kwargs): css_file = io.BytesIO(css_bytes) return CSS21Parser().parse_stylesheet_file(css_file, **kwargs)
def parse_bytes(css_bytes, kwargs): return CSS21Parser().parse_stylesheet_bytes(css_bytes, **kwargs)