def parse_error_response(self, response: etree.ElementBase) -> List[T.Error]: notifications = response.xpath(".//*[local-name() = $name]", name="Notifications") + response.xpath( ".//*[local-name() = $name]", name="Notification") return reduce(self._extract_error, notifications, [])
def _extract_quote(self, postage_node: etree.ElementBase) -> QuoteDetails: postage: RateRes.PostageType = RateRes.PostageType() postage.build(postage_node) currency = "USD" services: List[RateRes.SpecialServiceType] = [ (lambda s: (s, s.build(svc)))(RateRes.SpecialServiceType())[0] for svc in postage_node.xpath(".//*[local-name() = $name]", name="SpecialService") ] def get(key: str) -> Any: return reduce(lambda r, v: v.text, postage_node.findall(key), None) return QuoteDetails( carrier=self.client.carrier_name, service_name=None, service_type=get("MailService"), base_charge=None, duties_and_taxes=None, total_charge=float(postage_node.find("Rate").text), currency=currency, delivery_date=postage.CommitmentDate, discount=None, extra_charges=[ ChargeDetails( name=SpecialService(str(svc.ServiceID)).name, amount=svc.Price, currency=currency, ) for svc in services ], )
def extend_element( element: etree.ElementBase, children_or_attributes: Iterable[etree.ElementBase] ): for item in children_or_attributes: if isinstance(item, dict): element.attrib.update(item) continue if isinstance(item, str): try: previous_element = element[-1] except IndexError: previous_element = None if previous_element is not None: previous_element.tail = ( (previous_element.tail or '') + item ) else: element.text = ( (element.text or '') + item ) continue element.append(item)
def __init__(self, manga_element: etree.ElementBase, release_interval: timedelta): title = manga_element.cssselect('cite')[0].text self.chapter_decimal: Optional[int] = None ch = manga_element.cssselect('.simulpub-card__badge span')[0].text match = None if 'ex' in ch.lower(): match = self.SPECIAL_RE.match(ch) if match: ch = match.groups() self.chapter_decimal = 5 else: ch = ch.split('.') # If special chapter, set latest chapter to -1 if 'ex' in ch[0].lower(): latest_chapter = -1 else: latest_chapter = int(ch[0]) if len(ch) > 1: self.chapter_decimal = int(ch[1]) self.author = manga_element.cssselect('.proper-noun')[0].text title_id = manga_element.cssselect( '.card__link')[0].attrib['href'].strip('/').split('/')[-1] self.sources = [ Source(elem, self) for elem in manga_element.cssselect( '.simulpub-card__partners li a') ] self.release_date = datetime.utcnow()
def construct_ziotype_data(session, log_scope, document: etree.ElementBase) -> dict: fields = document.find("velden") omschrijving = trim_string( session, log_scope, find(fields, "naam"), 80, "omschrijving", ObjectTypenKeys.resultaattypen, ) return { "informatieobjecttype_omschrijving": omschrijving, "volgnummer": int(document.get("volgnummer")), "richting": get_choice_field( session, f"{log_scope} richting", find(fields, "type", False), RichtingChoices.values, ObjectTypenKeys.zaakinformatieobjecttypen, default=DEFAULT_RICHTING, ), # TODO no mapping for non-required fields # "statustype": "http://example.com" }
def export(xml_element: etree.ElementBase, **kwds) -> str: """Return a XML string. invoke the export method of generated type to return the subsequent XML represented """ output = StringIO() xml_element.export(output, 0, **kwds) return output.getvalue()
def _extract_package_rate( self, rates: List[T.QuoteDetails], detailNode: etree.ElementBase ) -> List[T.QuoteDetails]: rate = PRate.RatedShipmentType() rate.build(detailNode) if rate.NegotiatedRateCharges != None: total_charges = ( rate.NegotiatedRateCharges.TotalChargesWithTaxes or rate.NegotiatedRateCharges.TotalCharge ) taxes = rate.NegotiatedRateCharges.TaxCharges itemized_charges = rate.NegotiatedRateCharges.ItemizedCharges + taxes else: total_charges = rate.TotalChargesWithTaxes or rate.TotalCharges taxes = rate.TaxCharges itemized_charges = rate.ItemizedCharges + taxes extra_charges = itemized_charges + [rate.ServiceOptionsCharges] arrival = PRate.PickupType() [ arrival.build(arrival) for arrival in detailNode.xpath(".//*[local-name() = $name]", name="Arrival") ] currency_ = next(c.text for c in detailNode.xpath( ".//*[local-name() = $name]", name="CurrencyCode" )) return rates + [ T.QuoteDetails( carrier=self.client.carrier_name, currency=currency_, service_name=str(ShippingServiceCode(rate.Service.Code).name), service_type=rate.Service.Code, base_charge=float(rate.TransportationCharges.MonetaryValue), total_charge=float(total_charges.MonetaryValue), duties_and_taxes=reduce( lambda total, charge: total + float(charge.MonetaryValue), taxes or [], 0.0, ), discount=None, extra_charges=reduce( lambda total, charge: total + [ T.ChargeDetails( name=charge.Code, amount=float(charge.MonetaryValue), currency=charge.CurrencyCode, ) ], [charge for charge in extra_charges if charge != None], [], ), delivery_date=str(arrival.Date) ) ]
def from_section(cls, alias, section: etree.ElementBase, header_size=1): attributes = OrderedDict() props: Iterable[etree.ElementBase] = section.find('Properties') for prop in props: attributes[prop.tag] = alias.get_data_type_from_section( prop.find('Type')) none_section = section.find('AllowNone') allow_none = none_section is not None and none_section.text.strip() == 'true' return cls(attributes, allow_none)
def construct_statustype_data(session, log_scope, statustype: etree.ElementBase) -> dict: fields = statustype.find("velden") return { "volgnummer": int(statustype.get("volgnummer")), "omschrijving": find(fields, "naam"), "omschrijvingGeneriek": find(fields, "naam-model", False), "statustekst": find(fields, "bericht", False), # "informeren": true }
def parse_quote_response( self, response: etree.ElementBase ) -> Tuple[List[T.QuoteDetails], List[T.Error]]: details = response.xpath( ".//*[local-name() = $name]", name="FreightRateResponse" ) + response.xpath(".//*[local-name() = $name]", name="FreightRateResponse") if len(details) > 0: return self.parse_freight_rate_response(response) else: return self.parse_package_rate_response(response)
def _transform( self, token_generator: str, operation: Operation, element: etree.ElementBase, ): value = ''.join(element.itertext()) if not value: return element.clear() element.text = transform(value, operation, token_generator)
def from_section(cls, alias, section: etree.ElementBase, header_size): child_type = alias.get_data_type_from_section( section.find('of')) none_section = section.find('AllowNone') allow_none = none_section is not None and none_section.text.strip() == 'true' size_section = section.find('size') if size_section is not None: array_size = int(size_section.text.strip()) else: array_size = None return cls(child_type, array_size=array_size, allow_none=allow_none, header_size=1)
def _append_text(element: etree.ElementBase, text: Optional[str]) -> None: if not text: return last_child = _get_last_child_or_none(element) if last_child is not None and last_child.tail: last_child.tail = last_child.tail + '' + text elif last_child is not None: last_child.tail = text elif element.text: element.text = element.text + '' + text else: element.text = text
def get_or_create_element_at(parent: etree.ElementBase, path: List[str]) -> etree.ElementBase: if not path: return parent child = parent.find(TEI_NS_PREFIX + path[0]) if child is None: LOGGER.debug('creating element: %s', path[0]) tag_expression = parse_tag_expression(path[0]) child = tag_expression.create_node( element_maker=TEI_E ) parent.append(child) return get_or_create_element_at(child, path[1:])
def process_model(self, template_root: et.ElementBase, diagram_root: et.ElementBase): """Обработка модели и создание выходной диаграммы с использованием шаблона""" print("MODEL:") # print(model) pprint(self.model, indent=2, width=120) figure_templates: Dict[str, et.ElementBase] = {} for obj in template_root.findall(f'object[@type]'): obj_type: str = obj.attrib.get("type") figure_templates[obj_type] = obj print('TEMPLATE OBJECTS:') pprint(list(figure_templates.keys())) # словарь условных стилей, применяемых к фигурам в зависимости от значений их атрибутов # ключ = ключ из модели # значение - массив из xml-объектов, в каждом из которых определены свойства key, value и style # - key: используется в качестве ключа. # Стиль будет применен к фигурам, для которых в yml-модели указан данный ключ # - value: используется как селектор значений. # Будет применен стиль объекта, для которого в yml-модели для ключа key указано данное значение # - attributes: используется как селектор атрибутов. Список имен атрибутов, разделенный символом ';' # К целевой фигуре будут применены атрибуты форматирования фигуры со стилем, перечисленные в style style_templates: Dict[str, List[et.ElementBase]] = {} for obj in template_root.findall(f'object[@key]'): style_key: str = obj.attrib.get("key") if style_key not in style_templates: style_templates[style_key] = [] style_templates[style_key].append(obj) print('STYLE OBJECTS:') pprint(list(style_templates.keys())) # шаблонов фигур # for obj in figure_templates.values(): # obj.getparent().remove(obj) # # for styles in style_templates.values(): # for obj in styles: # obj.getparent().remove(obj) # обработаем модель root_figure: Figure = Figure() model = Model(figure_templates, style_templates, diagram_root) model.iterate(self.model, root_figure) root_figure.resize() # очистим выходную диаграмму от объектов, которых нет в модели for obj in diagram_root.findall(f'object'): if obj.attrib['id'] not in g_figures: diagram_root.remove(obj)
def _get_header_size_from_section(self, section: etree.ElementBase): """ E.g. <onEnterPreBattle> <Arg>BLOB</Arg> <VariableLengthHeaderSize> <WarnLevel>none</WarnLevel> </VariableLengthHeaderSize> </onEnterPreBattle> """ if section.find('VariableLengthHeaderSize'): return int(section.find('VariableLengthHeaderSize').text.strip()) return None
def replace_notelabel(el: ElementBase, text: str) -> None: '修改脚注的标签' while el.tag != 'a': el = el.getparent() if el.tag != 'a': a = el.find('.//a') if a is not None: el = a while len(el): el = el[0] el.text = text
def atom_document_to_feed(atom_url: str, tree: ElementBase) -> Feed: title = tree.findtext("{http://www.w3.org/2005/Atom}title") description = tree.findtext("{http://www.w3.org/2005/Atom}subtitle") category = tree.findtext("{http://www.w3.org/2005/Atom}category") link = tree.findtext("{http://www.w3.org/2005/Atom}link") or atom_url return Feed( url=atom_url, title=title, link=link, description=description, category=category, feed_source_type=FeedSourceType.ATOM, )
def from_section(cls, section: etree.ElementBase, alias): """ Create property object from xml section like following <ownShipId> <Type>ENTITY_ID</Type> <Flags>ALL_CLIENTS</Flags> <Default>0</Default> </ownShipId> """ type_ = alias.get_data_type_from_section(section.find('Type')) default = section.find('Default') flags = section.find('Flags').text.strip() return cls(section.tag, type_, flags=flags, default=default)
def _extract_quote( self, quotes: List[T.QuoteDetails], detailNode: etree.ElementBase ) -> List[T.QuoteDetails]: detail = RateReplyDetail() detail.build(detailNode) if not detail.RatedShipmentDetails: return quotes shipmentDetail: RatedShipmentDetail = detail.RatedShipmentDetails[0].ShipmentRateDetail delivery_ = reduce(lambda v, c: c.text, detailNode.xpath( ".//*[local-name() = $name]", name="DeliveryTimestamp" ), None) currency_ = reduce(lambda v, c: c.text, detailNode.xpath( ".//*[local-name() = $name]", name="Currency" ), None) Discounts_ = map( lambda d: T.ChargeDetails( name=d.RateDiscountType, amount=float(d.Amount.Amount), currency=currency_ ), shipmentDetail.FreightDiscounts, ) Surcharges_ = map( lambda s: T.ChargeDetails( name=s.SurchargeType, amount=float(s.Amount.Amount), currency=currency_ ), shipmentDetail.Surcharges, ) Taxes_ = map( lambda t: T.ChargeDetails(name=t.TaxType, amount=float(t.Amount.Amount), currency=currency_), shipmentDetail.Taxes, ) return quotes + [ T.QuoteDetails( carrier=self.client.carrier_name, service_name=detail.ServiceType, service_type=detail.ActualRateType, currency=currency_, delivery_date=datetime.strptime( delivery_, "%Y-%m-%dT%H:%M:%S" ).strftime("%Y-%m-%d") if delivery_ else None, base_charge=float(shipmentDetail.TotalBaseCharge.Amount), total_charge=float( shipmentDetail.TotalNetChargeWithDutiesAndTaxes.Amount ), duties_and_taxes=float(shipmentDetail.TotalTaxes.Amount), discount=float(shipmentDetail.TotalFreightDiscounts.Amount), extra_charges=list(Discounts_) + list(Surcharges_) + list(Taxes_), ) ]
def from_section(cls, alias, section: etree.ElementBase, header_size): type_section = section.find('Type') if type_section is None: logging.warning('%s does not provide type, what to do?', section) return None child_type = alias.get_data_type_from_section(type_section) return cls(child_type, header_size=1)
def from_section(cls, alias, section: etree.ElementBase, header_size): type_section = section.find('Type') if type_section is None: child_type = Blob() else: child_type = alias.get_data_type_from_section(type_section) return cls(child_type, header_size=1)
def _extract_intl_quote(self, service_node: etree.ElementBase) -> QuoteDetails: service: IntlRateRes.ServiceType = IntlRateRes.ServiceType() service.build(service_node) currency = "USD" special_services: List[IntlRateRes.ExtraServiceType] = [ (lambda s: (s, s.build(svc)))(IntlRateRes.ExtraServiceType())[0] for svc in service_node.xpath(".//*[local-name() = $name]", name="ExtraService") ] return QuoteDetails( carrier=self.client.carrier_name, service_name=None, service_type=service.MailType, base_charge=None, duties_and_taxes=None, total_charge=service.Postage, currency=currency, delivery_date=service.GuaranteeAvailability, discount=None, extra_charges=[ ChargeDetails( name=ExtraService(special.ServiceID).name, amount=special.Price, currency=currency, ) for special in special_services ], )
def find(el: etree.ElementBase, path: str, required=True) -> str: """find child element and return its text""" result = el.find(path).text if not result and required: raise ParserException(f"the element with path {path} is empty") else: return result or ""
def _extract_tracking(self, tracking_node: etree.ElementBase) -> TrackingDetails: tracking: TrackInfoType = TrackInfoType() tracking.build(tracking_node) details: List[TrackDetailType] = [ (lambda t: (t, t.build(detail)))(TrackDetailType())[0] for detail in tracking_node.xpath(".//*[local-name() = $name]", name="TrackDetail") ] return TrackingDetails( carrier=self.client.carrier_name, tracking_number=tracking.TrackInfoID, shipment_date=None, events=[ TrackingEvent( code=str(event.EventCode), date=event.EventDate, description=event.ActionCode, location=", ".join([ location for location in [ event.EventCity, event.EventState, event.EventCountry, str(event.EventZIPCode), ] if location is not None ]), time=event.EventTime, signatory=None, ) for event in details ], )
def _extract_tracking( self, trackings: List[T.TrackingDetails], shipmentNode: etree.ElementBase) -> List[T.TrackingDetails]: trackDetail = Track.ShipmentType() trackDetail.build(shipmentNode) activityNodes = shipmentNode.xpath(".//*[local-name() = $name]", name="Activity") def buildActivity(node): activity = Track.ActivityType() activity.build(node) return activity activities = map(buildActivity, activityNodes) return trackings + [ T.TrackingDetails( carrier=self.client.carrier_name, tracking_number=trackDetail.InquiryNumber.Value, events=list( map( lambda a: T.TrackingEvent( date=str(a.Date), time=str(a.Time), code=a.Status.Code if a.Status else None, location=a.ActivityLocation.Address.City if a.ActivityLocation and a.ActivityLocation. Address else None, description=a.Status.Description if a.Status else None, ), activities, )), ) ]
def parse_shipment_info( self, response: etree.ElementBase ) -> Tuple[T.ShipmentDetails, List[T.Error]]: shipment = (self._extract_shipment(response) if len( response.xpath(".//*[local-name() = $name]", name="shipment-id")) > 0 else None) return (shipment, self.parse_error_response(response))
def _xpath(node: etree.ElementBase, query: Text, *args, **kwargs) -> List[etree.ElementBase]: result = node.xpath(query, *args, **kwargs) if result is None: return [] if isinstance(result, etree.ElementBase): return [result] return result
def _find_with_ns(node: etree.ElementBase, query: Text) -> List[etree.ElementBase]: result = node.find(query, node.nsmap) if result is None: return [] if isinstance(result, etree.ElementBase): return [result] return list(result)
def parse_price_quotes( self, response: etree.ElementBase ) -> Tuple[List[T.QuoteDetails], List[T.Error]]: price_quotes = response.xpath(".//*[local-name() = $name]", name="price-quote") quotes: List[T.QuoteDetails] = reduce(self._extract_quote, price_quotes, []) return quotes, self.parse_error_response(response)
def parse_track_response( self, response: etree.ElementBase ) -> Tuple[List[T.TrackingDetails], List[T.Error]]: track_details = response.xpath(".//*[local-name() = $name]", name="Shipment") trackings: List[T.TrackingDetails] = reduce(self._extract_tracking, track_details, []) return (trackings, self.parse_error_response(response))
def __init__(self, element: etree.ElementBase, root, register=True): element.node = self self.element = element # :class:`etree.ElementBase` object representing this node in the xlm code. self.parents = [] #: List of paret objects. self.__children = None self.__file_name = None self.__root = root self.__register = register if register: self.root.register_node(self)
def create_child(self, element: etree.ElementBase): """ Finds NodeBase child class for a child element. There is no need to use this function. If this lookup behaviour has to be customized, override child_lookup(..) instead. """ if element.tag is etree.Comment: return if element.tag is etree.PI: return # If this is a ref element. Find the element it references and add it as a child. if element.tag == "ref": node_id = element.get("id") child = self.find_node_by_id(node_id) if child is None: raise IdNotFoundError(self.file_name, element.sourceline, node_id) else: # Check if this is a data Data element if isinstance(inspect.getattr_static(self, element.tag, None), Data): from urban_journey.ujml.nodes.data import data klass = data else: # Check if parent element knows what type it is. klass = self.child_lookup(element) # Update the node_register if it's empty. if len(node_register) == 0: update_plugins() # Look for node class in the register. if klass is None: if element.tag in node_register: klass = node_register[element.tag] else: # Node type was not found. raise UnknownElementError(self.file_name, element.sourceline, element.tag) child = klass(element, self.root) # Check if the super() was called in the __init__ of the node. if not hasattr(child, "element"): self.raise_exception(MissingSuperInitError, self.tag, element.tag) # Add child self.add_child(child)
def getparent(self, *args, **kwargs): result = ElementBase.getparent(self, *args, **kwargs) if result is None: return RomElement.window else: return result
def set(self, attr_name, attr_value): return ElementBase.set(self, attr_name, str(attr_value))