Skip to content

Fix line breaks / formatting on export --append #1038

Open

Description

@tuurep

Followup for #1036

Context: #1036 (comment), #1036 (comment), #1036 (review)

To summarize: on export --append, the resulting outfile is badly formatted in most cases, specifically:

@alexfikl:

Maybe by extending the exporter interface to do most of the work? I can't really see a way around it..

This sounds like it makes sense. I can probably work on this.

Activity

  1. alexfikl commented on Jul 7, 2025

    @alexfikl
    Collaborator

    yaml: doesn't insert --- in between documents on append

    This is a proper bug, since the result is incorrect (squishes two documents together). Same for the json exporter -- the result is not valid JSON.

    typst: can't export multiple docs (?)

    You mean our exporter? The format itself can definitely support multiple documents.

    This sounds like it makes sense. I can probably work on this.

    To expand a bit on this: to properly support json, it seems like we need to let the exporter do the file writing / appending. I'm inclined to suggest reworking the exporter plugins to be a little class similar to papis.importer.Importer that can do whatever it needs to. What did you have in mind?

  2. tuurep commented on Jul 7, 2025

    @tuurep
    ContributorAuthor

    typst: can't export multiple docs (?)

    You mean our exporter? The format itself can definitely support multiple documents.

    Yes, does this work for you?

    papis export -f typst --all

    I get this (--log DEBUG):

    [DEBUG] utils: Indexing folders in '/home/tuure/files/docs/papis'.
    [DEBUG] utils: Retrieved 56 valid folders.
    [DEBUG] utils: Finished in 36.2 ms.
    [DEBUG] database.cache: Computing 'papis_id' for each document.
    [DEBUG] database.cache: Loaded 56 documents.
    [DEBUG] database.cache: Querying database for '.'.
    [ERROR] commands.export: Failed to load 'typst' exporter. Cannot export to this format.
      ┆ Traceback (most recent call last):
      ┆   File "/usr/lib/python3.13/site-packages/papis/commands/export.py", line 88, in run
      ┆     .plugin(document for document in documents))
      ┆      ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      ┆   File "/usr/lib/python3.13/site-packages/papis/hayagriva.py", line 229, in exporter
      ┆     create_reference(doc): to_hayagriva(doc) for doc in documents
      ┆                            ~~~~~~~~~~~~^^^^^
      ┆   File "/usr/lib/python3.13/site-packages/papis/hayagriva.py", line 169, in to_hayagriva
      ┆     parent_known_keys = HAYAGRIVA_TYPE_PARENT_KEYS[htype]
      ┆                         ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
      ┆ KeyError: ''
    

    Also happens with any 2 documents. But a single document works.

    To expand a bit on this: to properly support json, it seems like we need to let the exporter do the file writing / appending. I'm inclined to suggest reworking the exporter plugins to be a little class similar to papis.importer.Importer that can do whatever it needs to. What did you have in mind?

    Yeah something along those lines, will have to look into it/experiment to find out more details :)

  3. alexfikl commented on Jul 7, 2025

    @alexfikl
    Collaborator

    Also happens with any 2 documents. But a single document works.

    This should be fixed by #1035. If you can test that, it would be great! 😁 It works for me for documents that are e.g. only article type.

  4. tuurep commented on Jul 7, 2025

    @tuurep
    ContributorAuthor

    Oh, that's completely right. I was unlucky with my testing in that at least one doc always just happened to not be article. I'll test your fix now.

    Edit: and even that whenever I tested a single document, it was article. I am a master at confusing myself 😄

    Do you agree that it would look better with an empty line between like:

    foo1
      bar1: baz1
      qux1: grault1
    
    foo2
      bar2: baz2
      qux2: grault2
    

    instead of

    foo1
      bar1: baz1
      qux1: grault1
    foo2
      bar2: baz2
      qux2: grault2
    

    ?

  5. tuurep commented on Jul 7, 2025

    @tuurep
    ContributorAuthor

    For the solution I had a high-level thought:

    Maybe it's possible that we retain the generic export func that writes the file, and the exporter plugin only has to give one piece of information: what is the separator between two distinct documents?

    Edit: right, it's not that simple in the json case though 🤔

  6. alexfikl commented on Jul 7, 2025

    @alexfikl
    Collaborator

    Do you agree that it would look better with an empty line between like:

    Can't say I feel strongly either way, but since everybody else gets a new line, might as well? It's just a YAML file in the end.

    Edit: right, it's not that simple in the json case though

    Yeah, the JSON exporter really makes this more complicated than it needs to be :\ I don't know.. maybe we can just have the exporter also return the separator and if it's None just say we can't append?

    EDIT: Actually, maybe it's better to bite the bullet. I also have a CSV exporter that wouldn't fit in the "just give me a separator" bucket very well (at least assuming it also has headers?).

  7. tuurep commented on Jul 7, 2025

    @tuurep
    ContributorAuthor

    EDIT: Actually, maybe it's better to bite the bullet. I also have a CSV exporter that wouldn't fit in the "just give me a separator" bucket very well (at least assuming it also has headers?).

    Yeah thanks for that context, let's be robust with it

  8. tuurep commented on Jul 7, 2025

    @tuurep
    ContributorAuthor

    For brainstorming's sake, maybe it's possible to reconceptualize appending as

    1. taking the set of documents that are currently in out.xyz (as a dict or something)
    2. adding to that set the docs to be appended
    3. overwriting with the complete set

    This however has the problem that if user has hand-written something in the outfile, would be undone

  9. jghauser commented on Jul 8, 2025

    @jghauser
    Member

    For brainstorming's sake, maybe it's possible to reconceptualize appending as

    1. taking the set of documents that are currently in `out.xyz` (as a `dict` or something)
    
    2. adding to that set the docs to be appended
    
    3. overwriting with the complete set
    

    This however has the problem that if user has hand-written something in the outfile, would be undone

    I kinda like this, at least if it can be done somewhat reasonably simply :). I think hand-written entries should be extremely rare (I mean if you're using Papis, might as well add that doc to the library). But maybe I'm missing some use case... (EDIT: and at least many such cases could be detected and the operation aborted)

  10. tuurep commented on Jul 8, 2025

    @tuurep
    ContributorAuthor

    Yeah, that approach would also, kinda by coincidence, solve #938 (comment):

    This also raises the issue of what to do on --append, since ensuring no duplicates means we need to read the existing file in, check it, possibly fix it, append the new documents, and write it back out.

    Heavily considering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions