phillipdupuis / pydantic-to-typescript

CLI Tool for converting pydantic models into typescript definitions
MIT License
285 stars 48 forks source link

Error when using CLI on multiple modules on OSX and Linux #5

Open schleind opened 3 years ago

schleind commented 3 years ago

I've tried this by defining a single module with multiple schema py's on OSX and Linux and am getting an error:

line 111, in remove_master_model_from_output new_lines = lines[:start] + lines[(end + 1) :] TypeError: unsupported operand type(s) for +: ‘NoneType’ and ‘int’

Looking at the code it seems that "end" is initialized to None and never is assigned, although maybe "start" isn't either. You're testing for a Windows line separator "\r\n" which means it won't work on OSX or Linux, but I believe you could fix it by replacing "\r\n" with os.linesep.

phillipdupuis commented 3 years ago

Hmm, if possible could you share the contents of the module it's failing on?

I've tested it out quite a bit on all operating systems, and I've never hit that error. And if you try this code out in a console, it should return true:

"test \r".rstrip("\r\n") == "test \r\n".rstrip("\r\n")
schleind commented 3 years ago

Hi, thanks for the response. Hopefully I'm not missing something simple...

Here's an example, a module called "gents", in the gents subdirectory, containing an empty init.py, plus two files, schema1.py: from pydantic import BaseModel

class Person(BaseModel): first_name: str last_name: str

schema2.py: from pydantic import BaseModel

class Address(BaseModel): street: str city: str state: str

I can generate a TypeScript file from either python file by using the command line: pydantic2ts --module gents.schema1 --output ./gents/pydantic.ts or pydantic2ts --module ./gents/schema2.py --output ./gents/pydantic.ts

But trying either pydantic2ts --module gents --output ./gents/pydantic.ts or pydantic2ts --module ./gents --output ./gents/pydantic.ts

... results in a stack trace like this: 2021-04-13 06:23:43,979 Finding pydantic models... 2021-04-13 06:23:43,979 The --module argument must be a module path separated by dots or a valid filepath Traceback (most recent call last): File "/pennant_ux/pennant_ux_env/bin/pydantic2ts", line 8, in sys.exit(main()) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/click/core.py", line 829, in call return self.main(args, kwargs) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/click/core.py", line 782, in main rv = self.invoke(ctx) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/click/core.py", line 1066, in invoke return ctx.invoke(self.callback, ctx.params) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/click/core.py", line 610, in invoke return callback(args, **kwargs) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/pydantic2ts/cli/script.py", line 222, in main return generate_typescript_defs(module, output, json2ts_cmd) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/pydantic2ts/cli/script.py", line 183, in generate_typescript_defs models = extract_pydantic_models(import_module(module)) File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/pydantic2ts/cli/script.py", line 49, in import_module raise e File "/pennant_ux/pennant_ux_env/lib/python3.8/site-packages/pydantic2ts/cli/script.py", line 39, in import_module module = module_from_spec(spec) File "", line 553, in module_from_spec AttributeError: 'NoneType' object has no attribute 'loader'

Any ideas? thanks in advance...

0x108 commented 2 years ago

Experiencing this error as well. Really love the library, would love for you to look into this - I have a quick 'fix' for this on Line 108 / 109, could you confirm this could be working?:

image
phillipdupuis commented 2 years ago

Hi @schleind -- sorry for taking so long to reply. Your error there is that the value you provide to --module is not a valid python module or filepath. It seems to be a directory.

This was a choice I made because it was much more straightforward to have this utility apply to a single module (and its submodules). Recursively searching through directories is messy, error-prone, and introduces other problems, such as naming collisions. However, I'm open to exploring it if there's a demand.

That said, I believe that if you have a gents/__init__.py file, the pydantic2ts --module gents.schema1 --output ./gents/pydantic.ts syntax should work.

phillipdupuis commented 2 years ago

And hi @0x108 -- again, sorry for taking so long to reply to this!

Are you still encountering this error? I've released a new version (v1.0.10) which touches this code, so it may be resolved now. If it's still an issue, I can make sure a fix is released within the next few days.

mfsjr commented 1 year ago

Hi @phillipdupuis, gents is a module containing an init.py, when I put one line of code into init.py "print('accessing module')" in gents, and run pydantic2ts --module gents --output ./gents/pydantic.ts I see it is being accessed as a module, successfully it seems:

2023-03-30 18:05:45,478 Finding pydantic models... accessing module 2023-03-30 18:05:45,480 Generating JSON schema from pydantic models... 2023-03-30 18:05:45,481 Converting JSON schema to typescript definitions...

Then I get a similar error, ending in: new_lines = banner_comment_lines + lines[:start] + lines[(end + 1) :] TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'