-
-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Override constructor with transformation function #33
Comments
I actually have been working adding a similar functionality but only for The reason I have implemented only for For instance, if I had a CSV file with a column CSV:
Code: from dataclass_csv import DataclassReader
from dataclasses import dataclass
@dataclass
class User:
name :str
def __post_init__(self):
self.name = self.name.upper()
def main():
with open("users.csv") as f:
reader = DataclassReader(f, User)
reader.map("firstname").to("name")
data = list(reader)
print(data)
if __name__ == "__main__":
main() Output:
That way it doesn't change so much the way of working with |
Your It is possible to use |
@dfurtado Thank you for creating this library. It is great and helped me quickly convert my dataclass to a CSV file. However I ran into a situation while writing the CSV file and I think @tewe's implementation suggestion could also work while writing. Consider this example: import sys
from typing import List
from dataclasses import dataclass, field
from dataclass_csv import DataclassWriter
@dataclass
class Score:
subject: str
grade: str
def __str__(self):
return "{} - {}".format(self.subject, self.grade)
@dataclass
class Student:
name: str
scores: List[Score] = field(default_factory=list)
def __str__(self):
return self.name
s = Student(
name="Student 1",
scores=[Score(subject="Science", grade="A"), Score(subject="Math", grade="A")],
)
with sys.stdout as csv_file:
writer = DataclassWriter(csv_file, [s], Student)
writer.write() The output for this is:
Following @tewe's example, to achieve an output like this:
We could do something like this: def format_scores(value) -> str:
return "|".join(["{}-{}".format(item.subject, item.grade) for item in value])
with sys.stdout as csv_file:
writer = DataclassWriter(csv_file, [s], Student)
writer.map("scores").using(format_scores)
writer.write() Or is there a better way to achieve this? |
Hello @karthicraghupathi , thanks a lot for the kind words about my project. Really appreciate it. Yes, I like this solution. I am actually working on something along those lines, trying out different solutions. I want to do something that will not feel unfamiliar when it comes to dataclasses usage and also the usage of the I'll ping you in this issue when I have something done. |
I got this error when using Traceback (most recent call last):
File "D:\code\python\cnki_crawler_playwright\main.py", line 202, in <module>
main()
File "D:\code\python\cnki_crawler_playwright\main.py", line 188, in main
w.map("paper_name").using(format_link)
AttributeError: 'HeaderMapper' object has no attribute 'using' And from the code, it seems dataclass-csv/dataclass_csv/header_mapper.py Lines 4 to 19 in 2dc71be
dataclass-csv/dataclass_csv/field_mapper.py Lines 4 to 18 in 2dc71be
|
@liudonghua123 You are right. It does not exist yet. This thread is to discuss @tewe's proposal and other ways of achieving that. We'll need to wait on @dfurtado to see which direction they take. |
Hi @karthicraghupathi and @liudonghua123 thanks for the contribution to this thread and using the lib. Yes, I see the use case for this for sure. I will try to put something together and create a PR. I think the first suggestion seems great, however it might make the API a bit complicate. The Let's say we have a column reader.map("First Name").to("firstname") In a case that I don't have any differences it would make the API inconsistent since the argument to map is the name of the column in the CSV, eg.: reader.map("firstname").using(fn) So it would be difficult to use from dataclass_csv import transform
def fn(value):
....
@dataclass
@transform("firstname", fn)
class User:
firstname: str
lastname: srt Please, share your thoughts about these solutions. |
To me "map using" isn't any less intuitive than "map to using", so I'd avoid introducing another name like The decorator way breaks down when you have two kinds of CSV you want to map to the same class. |
Hello 👋🏼 , As I have explained above having something like It could work do something like It would be fine when I have to put more though on this one to find a good solution that will look nice without breaking the current functionality. 🤔 |
Sorry, I didn't catch that distinction the first time. But what's wrong with |
I have another question, is there any ways to split some complex object properties to different columns? Say If I have the following classes for serialization to csv. @dataclass
class Link:
title: str
url: str
@dataclass
class SearchResult:
paper_name: Link
authors: list[Link]
publication: Link I would expected to have split |
@liudonghua123 I think that is a separate issue. I haven't tried if mapping a field twice already works. writer.map("paper_name").to("title")
writer.map("paper_name").to("url") But you'd additionally need something like the proposed API. writer.map("paper_name").to("url").using(lambda n: f"https://doi/{n}") |
@tewe Thanks, I will open a new issue to track. 😄 |
Hey, I took a look and this and it's possible to do this currently by overriding the test.csv:
then run:
Of course you can package them up in a nice method if you want :) |
This generalises #17.
Currently any class not special-cased by the library must have a constructor that takes a single string.
Even for built-in types this leads to workarounds like the following.
I think supporting transformation functions would add much-needed flexibility.
One possible syntax might be this.
The text was updated successfully, but these errors were encountered: