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

multiple independent packages, each with its own registry within a larger program #623

Closed
jkbgbr opened this issue Mar 16, 2018 · 10 comments

Comments

@jkbgbr
Copy link

jkbgbr commented Mar 16, 2018

The documentation says, quantities from different registries can not be used together. What happens if I have multiple packages developed independently, each with its own registry and want to use these in a larger program that uses said packages and the packages must communicate e.g. taking a result from package A and using it in package B.
As far as I understand the current logic, this would not work as simply importing the packages would break stuff. Is there a way to avoid having to implement some kind of a data exchange layer?

@hgrecco
Copy link
Owner

hgrecco commented Mar 23, 2018

The way I usually implemented this by having a flag in the subpackages to use pint's _DEFAULT_REGISTRY (usually through an environmental variable). The problem is when multiple packages have incompatible sets of units in which case is not possible with pint (but also is not logically possible)

@jkbgbr
Copy link
Author

jkbgbr commented Mar 26, 2018

I see. I also found #108 where you discussed this topic, it just did not come up when I googled it. I have a rather simple case (civil engineers usually don't define anything new) so using an unmodified default registry will solve my issues. Thanks for the answer!

@jkbgbr jkbgbr closed this as completed Mar 26, 2018
@bilderbuchi
Copy link
Contributor

Maybe the "fix" could be included as a note in the documentation, to spare later user the search?

@jkbgbr jkbgbr reopened this Mar 26, 2018
@jkbgbr
Copy link
Author

jkbgbr commented Mar 26, 2018

My solution for the current issue was:

ureg = _DEFAULT_REGISTRY

instead of

ureg = UnitRegistry()

and it seems to work; I don't know about side effects though.

@hgrecco
Copy link
Owner

hgrecco commented Mar 26, 2018

There are no side effects of this but maybe we could find a better API and document it.

@jkbgbr
Copy link
Author

jkbgbr commented Mar 26, 2018

how about class DefaultUnitRegistry(LazyRegistry): pass in registry.py?

@hgrecco
Copy link
Owner

hgrecco commented Dec 21, 2019

The current master has a default registry and an API to set the application registry. This should cover most applications. Feel free to reopen if needed.

@hgrecco hgrecco closed this as completed Dec 21, 2019
@bilderbuchi
Copy link
Contributor

Cool, thank you!
Is it already documented how to use this when creating (sub)packages and applications using them, as in the OP? I searched around on my phone but could not identify the relevant changesets to hunt this down.

@hgrecco
Copy link
Owner

hgrecco commented Dec 21, 2019

See #880 as a starting point. Feedback about the docs would be appreciated.

@bilderbuchi
Copy link
Contributor

Thank you for the pointer!
My feedback based on #880 changes:
The docstring for set_application_registry() only mentions unpickling operations. Also, the rst docs concerning serialisation explain its use in a pickling context. As writer of a simple package using units, I don't know what to do with this information. I don't (knowingly) use pickling? The docstring does not explain how I should structure my code for good interoperation with other pint-using packages.

I would suggest adding docs (maybe here would be a good spot) explaining how to do what the OP asks. I'll give a suggestion/template here of what I think makes sense, but I can't fill it out fully since I don't actually know what the "proper way is":

Interoperation between pint-using packages

When different packages and modules use pint, the proper handling of unit registries is critical. In addition, often you don't have access/freedom to change other people's code yourself. As a package author, you want to ensure that other people can easily work with your code. As an application author, you come into the situation where you use more than one pint-using package, and want to avoid clashes between three codebases.

Below we lay out a good structure how different packages modules, both packages and applications, can interoperate with each other when using pint.

Let's assume we have the following package structure, which should cover the majority of usecases. All packages make use of pint, and use the default registry if not otherwise indicated. Some are "unitful code providers", some "unitful code consumers", some both.

  • Package A is a package that primarily provides functionality to others, and is used widely (think numpy if you will).
  • Package B uses package A, can be used as an application, but is also imported and used that way (something like pytest comes to mind here)
  • Package C also provides unitful functionality, but without using other packages.
  • Package D* provides unitful code, but defines a custom registry (e.g. it adds custom units)
  • Package E is a package/application that consumes code directly from A, from A via B, from C and from D.

A sketch:

A
| \
| B C D*
\ | | /
  \ /
   E

To enable all these packages to play nice with each other (note: don't know if this is possible for D), the packages should do the following:

  • In package A, you should...
  • In package B, you should...
  • In package C, you should...
  • In package D, you should...
  • In package E, you should...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants