Git Product home page Git Product logo

Comments (8)

tzzh avatar tzzh commented on June 19, 2024 3

Starting from @piotr-yuxuan 's suggestion I used

def edn_to_map(x):
    if isinstance(x, edn_format.ImmutableDict):
        return {edn_to_map(k): edn_to_map(v) for k, v in x.items()}
    elif isinstance(x, edn_format.ImmutableList):
        return [edn_to_map(v) for v in x]
    elif isinstance(x, edn_format.Keyword):
        return x.name
    else:
        return x

it's incomplete but it seems ok so far in my case (parsing simple edns to python dicts without keywords), so posting it here in case that's helpful for someone else.

from edn_format.

bfontaine avatar bfontaine commented on June 19, 2024 2

I’ll let @swaroopch weight in but personnally I’d be interested in some option to edn_format.loads such as string_keys=True or string_keyword_keys=True that would parse all keyword keys as strings.

from edn_format.

piotr-yuxuan avatar piotr-yuxuan commented on June 19, 2024 1

I see two issues here:

  • Currently Keyword('a/b').name => 'a/b'. I'm sure it's kind of a Chersterton's fence and I'm not yet aware of why it has been built that way, but in Clojure (name :a/b) => "b". This precludes us to use a 'stringify' strategy which would return only simple names.
  • The way namespaced maps are done in the parser, and not in the lexer, further complicates any attempt to stringify keys. It's entirely possible that I'm wrong, but perhaps another way is possible by maintaining the map namespace in the lexer state (cf. here). This would seem more general to me, and less hackish. However, as I don't have yet the bigger picture, it's entirely possible that I miss a more important point.

These two points are very opinionated, and perhaps you will disagree with me. I would prefer to know the opinion of the maintainers about them before refactoring everything and making breaking changes ;-) If we were to move forward, I would see four possible different ways to parse an edn keyword, and two possible ways to parse a symbol:

  • Keyword
    • Default: Keyword object
    • String, :a/b -> a/b (clj namespace + clj name)
    • String, :a/b -> b (only the name, with possible shadowing)
    • String, :a/b -> :a/b (no-op)
  • Symbol
    • Default: Symbol object
    • String, '(fn [a] a) -> "(fn [a] a)"

Methinks a naive implementation for Keyword which store the parsing strategy as a lexer state would be:

@ply.lex.TOKEN(KEYWORD)
def t_KEYWORD(t):
    if t.lexer.keyword_parsing == KeywordParsing.keyword_object:
        t.value = Keyword(t.value[1:])
    elif t.lexer.keyword_parsing == KeywordParsing.name_string:
        t.value = Keyword(t.value[1:]).name
    elif t.lexer.keyword_parsing == KeywordParsing.ns_slash_name_string:
        t.value = t.value[1:]
    elif t.lexer.keyword_parsing == KeywordParsing.leading_colon_string:
        pass
    return t

…which leads to the remarks above.

from edn_format.

piotr-yuxuan avatar piotr-yuxuan commented on June 19, 2024

Indeed yes that sounds reasonable.

from edn_format.

swaroopch avatar swaroopch commented on June 19, 2024

Agree with @bfontaine ! Thanks @piotr-yuxuan :-)

from edn_format.

piotr-yuxuan avatar piotr-yuxuan commented on June 19, 2024

For the impatient, here how I would iterate through what is returned by edn_format:

keyword_name = lambda keyword: \
    keyword.name.split("/", 1)[1] if "/" in keyword.name else keyword.name
strinfigy_keyword = lambda x: \
    keyword_name(x) if isinstance(x, edn_format.Keyword) else x


def process_edn(x):
    if isinstance(x, edn_format.ImmutableDict):
        return {strinfigy_keyword(k): process_edn(v) for k, v in x.items()}
    elif isinstance(x, edn_format.ImmutableList):
        return [process_edn(v) for v in x]
    else:
        return strinfigy_keyword(x)

Obviously keyword_name can be changed for any other callable.

from edn_format.

bfontaine avatar bfontaine commented on June 19, 2024

Hello, sorry for the late response.

That’s interesting; I was thinking of post-processing the result of the parsing like you did in your second comment; not of doing that during the lexing/parsing.

Currently Keyword('a/b').name => 'a/b'

Yes, it has bit me before. I don’t know the reason behind this. Changing this would be a breaking change, though.

The way namespaced maps are done in the parser, and not in the lexer, further complicates any attempt to stringify keys.

I don’t understand how you would do that in the lexer; its job is to tokenize the input, not to make sense of those tokens. The lexer doesn’t know what a map looks like: in #:foo {:a 1}, #foo, {, :a, 1, and } are different tokens.

from edn_format.

mohkale avatar mohkale commented on June 19, 2024

Just thought it was worth mentioning that you can create a tag with @piotr-yuxuan solution. Which you can add at the top of your edn file if you don't want to actively call process_edn after parsing. Something like:

edn.add_tag('python', process_edn)

and then you can:

#python
{:tags
 [{:name "foo"},
  {:name "bar"} ]}

from edn_format.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.