Skip to content
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

[Issue 1325]: add python interactive console #1331

Merged
merged 18 commits into from
Feb 28, 2024
Merged

Conversation

rylew1
Copy link
Contributor

@rylew1 rylew1 commented Feb 26, 2024

Summary

Fixes #1325

Time to review: 5 min

Changes proposed

  • add make console target that loads Python interactive console

Context for reviewers

  • Want to get db session working, ability to query , and see Factory data
Screen.Recording.2024-02-26.at.5.48.26.PM.mov

@rylew1 rylew1 changed the title [1325]: add python interactive console [Issue 1325]: add python interactive console Feb 26, 2024
if isinstance(db, sqlalchemy.orm.scoped_session):
factories_module.db_session = db

variables["f"] = tests.src.db.models.factories
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI - we might want to adjust where this utility lives - I made it so the factories are only a test component with the dependencies as dev only. We shouldn't be importing them into the src path ideally. This code won't ever run non-locally, but if you tried to do so, it would complain about missing packages.

I'm not sure if the tests folder is quite the right place, but I did put a utility script in tests/lib/seed_local_db.py - might be worth coming up with a happier approach.

Copy link
Contributor Author

@rylew1 rylew1 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open but would propose splitting that piece out to a separate PR.

I do think it would make sense to close the loop on the intercepting session errors though - so that we don't have to manually do a rollback when it gets to an error state

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into the rollback automation, not finding a ton of approaches. Tried rolling back automatically when an error happens and that just cascades into other errors. In short, SQLAlchemy changed sessions to generally be made for handling a single set of transactions (great for an API, less so for an interactive console).

Without thinking through it much, the right approach probably involves lambdas/sessionmakers to automatically make new sessions when old ones error, but that's likely something that will take a while to figure out

Copy link
Contributor Author

@rylew1 rylew1 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to just approve and merge then after fixing the repr stuff? We've got db queries and ability to play with factories - that's a win I think.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can put that somewhere in the backlog, just adjust the repr bit and we can go from there

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Feb 27, 2024
return (f"<Opportunity(opportunity_id={self.opportunity_id}, "
f"opportunity_number='{self.opportunity_number}', "
f"opportunity_title='{self.opportunity_title}', "
f"agency='{self.agency}', category='{self.category}', ")
Copy link
Contributor Author

@rylew1 rylew1 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chouinar - hope its ok to add repr methods on the db models so printing is a little bit cleaner - where before it was just printing the object and mem address (I was having call a vars(object) on it to see the values). Maybe there's a better way though than manually spelling it out for each model though.

image

@rylew1 rylew1 self-assigned this Feb 27, 2024
@rylew1 rylew1 requested a review from chouinar February 27, 2024 02:47
@rylew1 rylew1 marked this pull request as ready for review February 27, 2024 04:41
Comment on lines 84 to 90
def __repr__(self) -> str:
return (
f"<Opportunity(opportunity_id={self.opportunity_id!r}, "
f"opportunity_number={self.opportunity_number!r}, "
f"opportunity_title={self.opportunity_title!r}, "
f"agency={self.agency!r}, category={self.category!r})"
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be an easier to maintain way that we could use - I'm going to break a lot of this with an upcoming set of refactors to the models. The models already have a for_json method that converts a model to a dictionary. If we instead add a repr function like this to the base class, we wouldn't need to add this to every class:

def __repr__(self) -> str:

     values = []
     for k, v in self.for_json().items():
         # Note that I see you added a format method to a lot of classes, probably call that on v here
         values.append(f"{k}={v!r}")

      
      return f"<{self.__class__.__name__}({','.join(values)})"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea the above worked - thanks!

Copy link
Contributor Author

@rylew1 rylew1 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a couple factories in the ootb vars!

@rylew1 rylew1 requested a review from chouinar February 27, 2024 20:57
Copy link
Collaborator

@chouinar chouinar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - just one minor note

Comment on lines 72 to 74
variables["OpportunityFactory"] = OpportunityFactory
variables["OpportunitySummaryFactory"] = OpportunitySummaryFactory
variables["OpportunityAssistanceListingFactory"] = OpportunityAssistanceListingFactory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have these all available on f.WhateverFactory already. Unless we want to add all of them like this (which is a lot to maintain) I'd prefer we just keep these in the f variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was more for typing convenience for some of the main models - but sure let's stick to f for now

@rylew1 rylew1 merged commit 8007004 into main Feb 28, 2024
8 checks passed
@rylew1 rylew1 deleted the rylew/1325-make-console branch February 28, 2024 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api ci/cd database documentation Improvements or additions to documentation python
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Task]: Add interactive python console to API as make console
2 participants