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-132: Revert API changes introduces with #86 #163

Merged
merged 1 commit into from
Feb 22, 2024

Conversation

Guzz-T
Copy link
Contributor

@Guzz-T Guzz-T commented Feb 13, 2024

With #86 we split the data from the read/write interface.
However, these changes mean that the existing program needs to be adjusted.

With this pull-request we restore the previous api by:

  • Add a data class that contains the parameters, calculations and visibilities
  • Keep the seperation of the data class and the read/write interface
  • Provide a new "Luxtronik" class that combines the data and the interface

This allows both the old and the new API to be used.

Fix #132

NOTE: The linter added some format changes.

Copy link

github-actions bot commented Feb 13, 2024

Coverage

Coverage Report
FileStmtsMissCoverMissing
luxtronik
   __init__.py17913425%39–51, 61–63, 70–74, 77, 81–86, 90–94, 105–108, 116–118, 125–127, 134–136, 143–145, 154, 162–164, 167–170, 173–176, 179–195, 198–212, 215–231, 234–248, 252–254, 258–259, 263–264, 275–277, 280, 283, 286, 289, 292–295, 298–301
   __main__.py21210%3–49
   datatypes.py275199%82
   discover.py403415%21–69
luxtronik/scripts
   dump_changes.py44440%5–85
   dump_luxtronik.py27270%5–52
TOTAL67326161% 

Tests Skipped Failures Errors Time
120 0 💤 0 ❌ 0 🔥 0.680s ⏱️

luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 14, 2024

Unfortunately read_parameters(self, parameters=Parameters(True) doesn't work reliably. The first time an instance is created. From the second call onwards, the reference is still stored, which means that no new instance is created.

@gerw
Copy link
Collaborator

gerw commented Feb 14, 2024

But this is fixed by moving Parameters(True) to the function body in the latest patch, right?

Btw: True is the default argument of Parameters() and can be omitted.

The reason seems to be the following, I didn't know that either.

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

Reference

luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 14, 2024

But this is fixed by moving Parameters(True) to the function body in the latest patch, right?

Yes, that has already been adjusted.

@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 14, 2024

Btw: True is the default argument of Parameters() and can be omitted.

Done

@gerw
Copy link
Collaborator

gerw commented Feb 15, 2024

The copy() method does a shallow copy. We also (instead?) need a deep copy:

class LuxtronikData:
[...]
    @classmethod
    def deepcopy(cls, data):
        return LuxtronikData(deepcopy(data.parameters), deepcopy(data.calculations), deepcopy(data.visibilities))

With this addition, consider this snippet:

from luxtronik import LuxtronikData
import copy
import timeit

l = LuxtronikData()

l.parameters.get(0).raw = 1

print("l.parameters.get(0).raw =", l.parameters.get(0).raw)

l2 = LuxtronikData.copy(l)
l3 = copy.copy(l)
l4 = copy.deepcopy(l)
l5 = LuxtronikData.deepcopy(l)

print("===")

l.parameters.get(0).raw = 2

print("l.parameters.get(0).raw  =", l.parameters.get(0).raw)
print("l2.parameters.get(0).raw =", l2.parameters.get(0).raw)
print("l3.parameters.get(0).raw =", l3.parameters.get(0).raw)
print("l4.parameters.get(0).raw =", l4.parameters.get(0).raw)
print("l5.parameters.get(0).raw =", l5.parameters.get(0).raw)

print("===")
num = 100
s = """
from luxtronik import LuxtronikData
import copy
l = LuxtronikData()
"""
print(timeit.timeit('l2 = LuxtronikData.copy(l)', setup=s, number=num)/num)
print(timeit.timeit('l3 = copy.copy(l)', setup=s, number=num)/num)
print(timeit.timeit('l4 = copy.deepcopy(l)', setup=s, number=num)/num)
print(timeit.timeit('l5 = LuxtronikData.deepcopy(l)', setup=s, number=num)/num)

Output for me:

l.parameters.get(0).raw = 1
===
l.parameters.get(0).raw  = 2
l2.parameters.get(0).raw = 2
l3.parameters.get(0).raw = 2
l4.parameters.get(0).raw = 1
l5.parameters.get(0).raw = 1
===
4.6712099992873845e-06
1.3894300013816973e-06
0.00908147751999877
0.009089312020000762

Thus:

  • The two copy() methods do not work as intended.
  • The deepcopy() are quite slow. On my (rather fast) machine, they need 0.01 seconds.
  • The deepcopy() from the copy module is good enough and we do not need to implement our own deepcopy() method.

I think that we can also drop new() by using

class LuxtronikData:
    """
    Collection of parameters, calculations and visiblities.
    Also provide some high level access functions to their data values.
    """

    def __init__(self, parameters=None, calculations=None, visibilities=None, safe=True):
        self.parameters = Parameters(safe) if parameters is None else parameters
        self.calculations = Calculations() if calculations is None else calculations
        self.visibilities = Visibilities() if visibilities is None else visibilities

luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
luxtronik/__init__.py Outdated Show resolved Hide resolved
@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 15, 2024

The deepcopy() from the copy module is good enough and we do not need to implement our own deepcopy()

I think that we can also drop new() by using

Done

luxtronik/__init__.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@gerw gerw left a comment

Choose a reason for hiding this comment

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

I think that I am (almost) satisfied with the changes in __init__.py. (I didn't check the other files yet.)

Thanks for the great work!

luxtronik/__init__.py Show resolved Hide resolved
@gerw
Copy link
Collaborator

gerw commented Feb 16, 2024

I have made some changes to the other files. Now, I am fine with the PR

@Guzz-T : Can you please rebase to main and squash all these commits to a single one?

@Bouni @kbabioch : What do you think about the PR?

@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 17, 2024

@Guzz-T : Can you please rebase to main and squash all these commits to a single one?

Done

@Bouni
Copy link
Owner

Bouni commented Feb 19, 2024

LGTM I highly like the fact that we unbreak the API 😄

Copy link
Collaborator

@gerw gerw left a comment

Choose a reason for hiding this comment

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

IMHO, only two minor things are left. And the commit message "Add a decorator to provide the previous api" might be a copy-and-paste leftover from the last PR?

I am looking forward to merging this.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@gerw gerw mentioned this pull request Feb 19, 2024
@Guzz-T
Copy link
Contributor Author

Guzz-T commented Feb 20, 2024

IMHO, only two minor things are left. And the commit message "Add a decorator to provide the previous api" might be a copy-and-paste leftover from the last PR?

Now use the title of this pull-request.

@gerw gerw added this to the New pypi release 0.3.15 milestone Feb 21, 2024
@Bouni
Copy link
Owner

Bouni commented Feb 22, 2024

I think everything is resolved and ready. I'll merg it.

@Bouni Bouni merged commit 14bc7b8 into Bouni:main Feb 22, 2024
4 checks passed
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

Successfully merging this pull request may close these issues.

Parameters (and friends) should be members of Luxtronik
3 participants