<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Extracting a Custom Property
Step1:  Example Document
Let's create a simple example document with a single heading followed by a single paragraph
Step2:  What does this look like
Step3:  Default Parsers
By default, ChemDataExtractor won't extract the boiling point property
Step4:  Defining a New Property Model
The first task is to define the schema of a new property, and add it to the Compound model
Step5:  Writing a New Parser
Next, define parsing rules that define how to interpret text and convert it into the model
Step6:  Running the New Parser
<ASSISTANT_TASK:>
Python Code:
from chemdataextractor import Document
from chemdataextractor.model import Compound
from chemdataextractor.doc import Paragraph, Heading
Explanation: Extracting a Custom Property
End of explanation
d = Document(
    Heading(u'Synthesis of 2,4,6-trinitrotoluene (3a)'),
    Paragraph(u'The procedure was followed to yield a pale yellow solid (b.p. 240 °C)')
)
Explanation: Example Document
Let's create a simple example document with a single heading followed by a single paragraph:
End of explanation
d
Explanation: What does this look like:
End of explanation
d.records.serialize()
Explanation: Default Parsers
By default, ChemDataExtractor won't extract the boiling point property:
End of explanation
from chemdataextractor.model import BaseModel, StringType, ListType, ModelType
class BoilingPoint(BaseModel):
    value = StringType()
    units = StringType()
    
Compound.boiling_points = ListType(ModelType(BoilingPoint))
Explanation: Defining a New Property Model
The first task is to define the schema of a new property, and add it to the Compound model:
End of explanation
import re
from chemdataextractor.parse import R, I, W, Optional, merge
prefix = (R(u'^b\.?p\.?$', re.I) | I(u'boiling') + I(u'point')).hide()
units = (W(u'°') + Optional(R(u'^[CFK]\.?$')))(u'units').add_action(merge)
value = R(u'^\d+(\.\d+)?$')(u'value')
bp = (prefix + value + units)(u'bp')
from chemdataextractor.parse.base import BaseParser
from chemdataextractor.utils import first
class BpParser(BaseParser):
    root = bp
    def interpret(self, result, start, end):
        compound = Compound(
            boiling_points=[
                BoilingPoint(
                    value=first(result.xpath('./value/text()')),
                    units=first(result.xpath('./units/text()'))
                )
            ]
        )
        yield compound
Paragraph.parsers = [BpParser()]
Explanation: Writing a New Parser
Next, define parsing rules that define how to interpret text and convert it into the model:
End of explanation
d = Document(
    Heading(u'Synthesis of 2,4,6-trinitrotoluene (3a)'),
    Paragraph(u'The procedure was followed to yield a pale yellow solid (b.p. 240 °C)')
)
d.records.serialize()
Explanation: Running the New Parser
End of explanation
<END_TASK>