In which @Captain tries to extend a Python app to use MathJax



  • OK, this task "feels" like it is almost done. But the app is python based, and I am having a syntax error I don't understand. The line is:

    return re.sub(jaxReg%("\\d","\\d"), "\\2" || "\\4", txt)
    

    and Python complains about a "syntax error" at the second \\d. It is not more specific. It just says "Syntax error" and points to second \\d (but not the first).

    The function I am writing (and monkey patching, ugh) is:

    jaxReg = r"(\$+).*?\{\{c{s}::(.*?)\}\}[^\$]*(\$+)?|\{\{c{s}::(.*?)\}\}"
    
    def clozeJax(self, txt, ord, type):
        if not re.search(jaxReg%(ord, ord), txt):
            return ""
        def repl(m):
            # replace chosen cloze with type
            if type == "q":
                 if m.group(1):
                 return "\\text{[...]}"
                 else: 
                     return "<span class='cloze'>[...]</span class='cloze'>"
            else:
                 return "%s" % m.group(3)
            txt = re.sub(jaxReg%(ord, ord), repl, txt)
            # and display other clozes normally
            return re.sub(jaxReg%("\\d","\\d"), "\\2" || "\\4", txt)
    
    Template.clozeText = clozeJax
    

    (so the problem is in the very last line of the clozeJax definition)

    Any ideas? Am I missing something dumb?



  • I get a syntax error on the ||, which isn't a valid operator in Python. Did you mean + for string concatentation?

    I don't know why you'd get a syntax error on the second ""\\d".



  • @Dragnslcr said in In which @Captain tries to extend a Python app to use MathJax:

    I get a syntax error on the ||, which isn't a valid operator in Python. Did you mean + for string concatentation?

    Aha, okay, that makes sense I guess. I definitely don't mean +, but I guess it would work. :-)

    What I "really" want is something that short circuit checks if a is defined and if not checks if b is defined in a ???? b, where ???? is some operator.

    I tried +, and it fixes the syntax error, but now it's complaining that a is None at runtime. I guess I can sort it from here.


  • Winner of the 2016 Presidential Election

    @Captain said in In which @Captain tries to extend a Python app to use MathJax:

    What I "really" want is something that short circuit checks if a is defined and if not checks if b is defined in a ???? b, where ???? is some operator.

    In that case, you should probably remember that this is not Haskell and that arguments are evaluated before invoking the function. So even if this operator existed, it wouldn't do what you want since it would be evaluated before the actual replacement happens. ;)

    Fortunately for you, re.sub supports a function as the second argument. That's probably what you want.



  • I'm seeing some things here that I am really... ah, not very clear on, at the very least. let's go step by step on this, shall we?

    First off, though: what version of Python are you using? While I don't see anything here that should be specific to 2.x or 3.x, it may be relevant. The main reason I ask is because you are using the % string interpolation operator a lot, and in 3.x the .format() method is generally preferred over the interpolation operator.

     jaxReg = r"(\$+).*?\{\{c{s}::(.*?)\}\}[^\$]*(\$+)?|\{\{c{s}::(.*?)\}\}"
    

    OK, this looks fine... except that later in the code, you apply string interpolations to it, and there aren't any interpolation specifiers (which always start with a percent sign %, and use a variant of the C sprintf() formatting syntax). This means that you don't actually have anywhere to insert the interpolations to.

     def clozeJax(self, txt, ord, type):
    

    Uhm, is this a method? While the identifier self isn't actually a keyword, it is conventional to use it only for the object reference of an instance method. You did say it was getting monkeypatched, so I don't know just how you are handling inserting it if it is part of a class, but it still seems odd here, especially since the function doesn't use it to reference any instance variables.

         if not re.search(jaxReg%(ord, ord), txt):
             return ""
         def repl(m):
    

    You are defining an inner function here, but it doesn't seem to get used. No, wait, you're passing it as a closure to re.sub() later... huh? I don't think that will work - did you mean to call the function? checks language ref Oh, OK, that is valid, I guess.

             # replace chosen cloze with type
             if type == "q":
                  if m.group(1):
                  return "\\text{[...]}"
                  else: 
                      return "<span class='cloze'>[...]</span class='cloze'>"
    

    I am assuming that this is meant to be HTML, but I'm pretty sure attributes aren't legal in a closing tag.

             else:
                  return "%s" % m.group(3)
    

    How is "%s" % m.group(3) different from m.group(3), assuming that m.group(3) is in fact a string-convertable type? The only reason I can think for this would be to force a fail-fast situation (because the interpolation op would throw an error if it is either None or some type that doesn't implement str()), but wouldn't testing for the validity of m.group(3) and raising an error on failure make more sense?

             return re.sub(jaxReg%("\\d","\\d"), "\\2" || "\\4", txt)
    

    The Perl-style short-circuit you are aiming for is invalid in Python, as already noted; not only is the operator for logical-or actually or, but also only applies to strict booleans.

    EDIT: corrected a dumbass attack re: the logical op.


  • area_pol

    @Captain said in In which @Captain tries to extend a Python app to use MathJax:

    checks if a is defined and if not checks if b is defined in a ???? b

    Maybe or?

    In [1]: a = None
    In [2]: b = "hello"
    In [5]: a or b
    Out[5]: 'hello'
    


  • @Adynathos OK, I didn't realize that would work. Crap, I fucked up there.


  • area_pol

    @ScholRLEA
    Another useful structure is: a if cond else b:

    In [9]: 1/0 if False else 0
    Out[9]: 0
    


  • @ScholRLEA said in In which @Captain tries to extend a Python app to use MathJax:

    I'm seeing some things here that I am really... ah, not very clear on, at the very least. let's go step by step on this, shall we?

    First off, though: what version of Python are you using? While I don't see anything here that should be specific to 2.x or 3.x, it may be relevant. The main reason I ask is because you are using the % string interpolation operator a lot, and in 3.x the .format() method is generally preferred over the interpolation operator.

     jaxReg = r"(\$+).*?\{\{c{s}::(.*?)\}\}[^\$]*(\$+)?|\{\{c{s}::(.*?)\}\}"
    

    OK, this looks fine... except that later in the code, you apply string interpolations to it, and there aren't any interpolation specifiers (which always start with a percent sign %, and use a variant of the C sprintf() formatting syntax). This means that you don't actually have anywhere to insert the interpolations to.

    Yup, that's my mistake. Those {s} were string interpolations like %s until I tried to fix the syntax error and then I forgot to keep the code consistent.

     def clozeJax(self, txt, ord, type):
    

    Uhm, is this a method? While the identifier self isn't actually a keyword, it is conventional to use it only for the object reference of an instance method. You did say it was getting monkeypatched, so I don't know just how you are handling inserting it if it is part of a class, but it still seems odd here, especially since the function doesn't use it to reference any instance variables.

    Yeah, the clozeText method is defined by

    def clozeText(self, txt, ord, type):
       stuffLikeMineButDifferent
    

    Per the monkey patching tutorial for the app, I'm just overwriting clozeText by clozeJax.

         if not re.search(jaxReg%(ord, ord), txt):
             return ""
         def repl(m):
    

    You are defining an inner function here, but it doesn't seem to get used. No, wait, you're passing it as a closure to re.sub() later... huh? I don't think that will work - did you mean to call the function? checks language ref Oh, OK, that is valid, I guess.

    Yeah, I didn't modify that part of the original clozeText function.

             # replace chosen cloze with type
             if type == "q":
                  if m.group(1):
                  return "\\text{[...]}"
                  else: 
                      return "<span class='cloze'>[...]</span class='cloze'>"
    

    I am assuming that this is meant to be HTML, but I'm pretty sure attributes aren't legal in a closing tag.

    That's another issue in the original source, but I can clean it up easily. :-)

             else:
                  return "%s" % m.group(3)
    

    How is "%s" % m.group(3) different from m.group(3), assuming that m.group(3) is in fact a string-convertable type?

    More original source problems. Will fix too.

             return re.sub(jaxReg%("\\d","\\d"), "\\2" || "\\4", txt)
    

    The Perl-style short-circuit you are aiming for is invalid in Python, as already noted; not only is the operator for logical-or actually or, but also only applies to strict booleans.

    :sadface:



  • @Captain As I noted in my reply to @Adynathos, I was wrong about the or only working on booleans - I tend not to rely on truthiness, and in any case I would have expected a boolean op that operates on truthy values to return True rather than the truthy value. Dunno why, every language that uses truthiness which I know of will do that, but it didn't occur to me.


Log in to reply