Django typehinting - django

I created an empty migration, which now looks like this:
def forwards(apps, schema_editor):
Foo = apps.get_model('app', 'Foo')
FixedResponse.objects.create(name='Bar')
def backwards(apps, schema_editor):
Foo = apps.get_model('app', 'Foo')
Foo.objects.filter(name='Bar').delete()
class Migration(migrations.Migration):
dependencies = [
('app', '0035_fixedresponse'),
]
operations = [
migrations.RunPython(forwards, backwards)
]
Since there is no Django documentation anywhere on this topic (migrations specific) or best practice,
I want to know how do I type hint the code above?

There is no universal answer to that question, and the only reputable source you will find about it is Django's reference and documentation, which don't make any mention about annotations for migrations.
The "correct way to handle type hinting in Django" strictly depends on your company's policy. Prior to asking how, you must ask why. Once you know why, figuring out how will likely be straightforward. However, if instead of asking "why?", you (or your boss) ask "why not?", that's taking the issue upside down. You need a reason to do something, but you don't need a reason not to do something. (1)
If the reason is "to pass CI", this is no valid reason. CI is meant to work for you, not the opposite.
If the reason is "to document the code", this is no valid reason either. Type hints are documentation, the purpose of writing documentation is not "to document the code". Why is any documentation needed? Who is going to read this documentation? What information do they need that is not already clear in the code?
I see 3 valid reasons to use type hints:
Provide help for developers using the functions. In the case of migrations, forwards and backwards functions are only used internally by Django. Developers reading your code are expected to have knowledge about migrations. If they don't know what apps and schema_editor are, it seems fair to expect them to refer to migrations.RunPython documentation, rather than re-explaining it for every single backwards and forwards callbacks of every single RunPython operation of every single migration.
QA type checking. But type checking is only useful for your own code. You'll never import the functions from migrations to use them in your code, so there is nothing to check.
Provide meta information for some smart tools (internal or third party) using introspection to do magic stuff.
Unless your case fits in one of these three, or you have any other reason to use type hints, don't try to fit to "policies" blindly. Don't write annotations just because you can. Keep calm and (re)read the Zen of Python. :) (2)
TLDR: Ask your boss to tell you why he wants type hints for migrations. If the answer is a well-defined purpose, write hints to serve that purpose. If the answer is anyhow stupid, write stupid type hints. ¯\(ツ)/¯ (3)
Footnotes
(1) The double negation might be confusing. What I mean here is that if someone can't explain the purpose of doing something, you don't need to find the purpose of not doing it. Or at least, there is a very straightforward purpose: saving the time and resources required to do it and maintain it.
(2) Don't try to find any principle specific to this situation in the Zen of Python. I only meant this reference as a general reminder of Python's philosophy: keep things simple, clear explicit code is worth more than poor paraphrasing documentation, that kind of stuff.
(3) If the purpose is "to pass CI" or such, I'd personally recommend something silly like def forwards(apps: ..., schema_editor: ...) -> ... (I mean, literally annotate with the Ellipsis object). Either nobody notice and it was indeed pointless, either your boss or your colleagues throw it back at you and hopefully come with a better defined purpose.

The documentation:
code (and reverse_code if supplied) should be callable objects that accept two arguments; the first is an instance of django.apps.registry.Apps containing historical models that match the operation’s place in the project history, and the second is an instance of SchemaEditor.
https://docs.djangoproject.com/en/stable/ref/migration-operations/#django.db.migrations.operations.RunPython
So, if you want to annotate your data migrations with types, these are the appropriate annotations:
from django.apps.registry import Apps
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def forwards(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
...

Related

framework/library for property-tree-like data structure with generic get/set-implementation?

I'm looking for a data structure which behaves similar to boost::property_tree but (optionally) leaves the get/set implementation for each value item to the developer.
You should be able to do something like this:
std::function<int(void)> f_foo = ...;
my_property_tree tree;
tree.register<int>("some.path.to.key", f_foo);
auto v1 = tree.get<int>("some.path.to.key"); // <-- calls f_foo
auto v2 = tree.get<int>("some.other.path"); // <-- some fallback or throws exception
I guess you could abuse property_tree for this but I haven't looked into the implementation yet and I would have a bad feeling about this unless I knew that this is an intended use case.
Writing a class that handles requests like val = tree.get("some.path.to.key") by calling a provided function doesn't look too hard in the first place but I can imagine a lot of special cases which would make this quite a bulky library.
Some extra features might be:
subtree-handling: not only handle terminal keys but forward certain subtrees to separate implementations. E.g.
tree.register("some.path.config", some_handler);
// calls some_handler.get<int>("network.hostname")
v = tree.get<int>("some.path.config.network.hostname");
search among values / keys
automatic type casting (like in boost::property_tree)
"path overloading", e.g. defaulting to a property_tree-implementation for paths without registered callback.
Is there a library that comes close to what I'm looking for? Has anyone made experiences with using boost::property_tree for this purpose? (E.g. by subclassing or putting special objects into the tree like described here)
After years of coding my own container classes I ended up just adopting QVariantMap. This way it pretty much behaves (and is as flexible as) python. Just one interface. Not for performance code though.
If you care to know, I really caved in for Qt as my de facto STL because:
Industry standard - used even in avionics and satellite software
It has been around for decades with little interface change (think about long term support)
It has excellent performance, awesome documentation and enormous user base.
Extensive feature set, way beyond the STL
Would an std::map do the job you are interested in?
Have you tried this approach?
I don't quite understand what you are trying to do. So please provide a domain example.
Cheers.
I have some home-cooked code that lets you register custom callbacks for each type in GitHub. It is quite basic and still missing most of the features you would like to have. I'm working on the second version, though. I'm finishing a helper structure that will do most of the job of making callbacks. Tell me if you're interested. Also, you could implement some of those features yourself, as the code to register callbacks is already done. It shouldn't be so difficult.
Using only provided data structures:
First, getters and setters are not native features to c++ you need to call the method one way or another. To make such behaviour occur you can overload assignment operator. I assume you also want to store POD data in your data structure as well.
So without knowing the type of the data you're "get"ting, the only option I can think of is to use boost::variant. But still, you have some overloading to do, and you need at least one assignment.
You can check out the documentation. It's pretty straight-forward and easy to understand.
http://www.boost.org/doc/libs/1_61_0/doc/html/variant/tutorial.html
Making your own data structures:
Alternatively, as Dani mentioned, you can come up with your own implementation and keep a register of overloaded methods and so on.
Best

Why allInstance not for isUnique?

I have a class Client with attribute noClient, I wan to verify there is no client with the same noClient.
I have the solution below, but the teacher said its not appropriate. Because the contraint may be repeated. I don't know why. And I need to find another solution.
context Client
inv NoClientUnique: Client.allInstances -> isUnique (noClient)
My problem is, I don't even know what is the problem with the code above to be able to find another solution.
This this a school question. Maybe not enough challenging out there, but I spend hours trying to understand. I'm stuck here.
Apart from minor syntactical mistakes (should be allInstances()-> ) I don't see a problem with your expression. Make sure you didn't misunderstood your teacher regarding what the constraint was supposed to constrain
I just saw in an example, my teacher created a class Singleton, then use the Singleton as context, and not the Client.
class Singleton
-- nothing here.
end
...
context Singleton
inv SingletonisUnique : Singleton.allInstances -> size() = 1
inv noClientUnique : Client.allInstances -> isUnique(noClient)
I think this is the key to my problem, but I don't understand what's the mechanism there.
As far as I know, in a typing vision, the OclExpr in parameter should be a boolean expression to evaluate, which is not the case here.
Of course, the result will vary from one OCL tool to another.
Your teacher is correct in that with typical OCL tools evaluation of all Clients will be repeated for each Client.
But your teacher is also wrong in that a decent OCL tool should optimize the self-less invariant to achieve the same effect as the spurious Singleton. Tools should help the users not force users to manually optimize.
More realistically, the container of Client may perhaps be Business and you could more sensibly express the business practice that noClient is unique in Business since it isn't really a Client constraint.
Another option would be:
context Client
inv NoClientUnique: Client.allInstances()->forAll(c1, c2 : Client | c1 <> c2 implies c1.noClient <> c2.noClient)
For anyone else looking for the answer in 2020:
Client.allInstances().collect(noClient) -> count(noClient) = 1
I'm using USE from Bremen University and the isUnique() operation does not work as intended. Took me awhile to figure out an alternative.

How do I add an if statement to the postcondition of a schema?

I'll simplify things for this scenario (It's in Perfect Developer, it gets complex quite quickly). Let's say I have a simple schema in my class, called Succeed, which takes a Course (which is a previously defined class) as parameter.
Basically, I want to be sure that the course is in my courses set as a precondition, and then add it to my coursesCompleted set in my postcondition. This simple schema works great, and looks like this :
schema !Succeed(c:Course)
pre
c in allCourses
post
coursesCompleted! = coursesCompleted.append(c);
However, I want to add a quite simple if condition: If my coursesCompleted cardinality is 30 or more, I want to set a Diplomation enum to, let's say, "Ok". If the cardinality is less than 30, I will set it to "NotOk"
According to Perfect Developer's documentation, and all the rare examples I've seen, the if syntax should look like this :
if [condition1] : do stuff;
[condition2] : do other stuff;
fi
However, if I plug that directly in my schema, as is :
schema !Succeed(c:Course)
pre
c in allCourses
post
coursesCompleted! = coursesCompleted.append(c),
if [#coursesCompleted >= 30] : diplomation = Ok#DiplomationEnum;
[#coursesCompleted < 30] : diplomation = NotOk#DiplomationEnum;
fi
it does not work, I always end up with a "very descriptive"
Error! Syntax error at keyword 'if', expected one of: '!' '(' '?'
'c_address_of'
I've tried adding some ; everywhere, adding a via keyword after the post, changing it's position, trading ;s with ,, and a lot of other trial and error stuff.
So my question is: How can I add a if condition to a postcondition of a schema, in Perfect Developer?
Please answer in Perfect Developer. I (sadly) know my formal methods, I only need the if to compile in the worst tool in the world.
I can provide a solution in formal-methods using the zet notation, since I am not using Perfect Developer, however, that program should be based on formal-methods. As far as I know in formal methods, if conditions are not used when the system has different behavior over some preconditions, but rather you create 2 methods with different
preconditions(the way i implemented it) or a nested method covering both scenarios, seperated with a Logic OR in between. When it comes to error handling, you first provide a best case scenario and then define a robust method definition(schema calculus).
In formal methods the notation ! is used to describe the output while ? is used for the input.
I hope that this will help you understand possible issues, since its not a direct perfect-developer solution. However, considering the fact that in formal methods mathematics are used, you can use the following specification and jump to any program/language for the implementation part.
Note that: Anything that you will see in the following schemata on the preconditions/how the system changes part, is connected with a logic AND, however I am not using the symbol because is implied as far as a logic OR is not used.
So here is how it will look like in formal-methods(Z-notation).

Naming confusion? Is having objects named FlowerGroup and FlowerGroups confusing?

I'm writing a program and I seem to be creating alot of objects where one object will be the singular form and then the collection is the plural form. eg
SalesGroup
SalesGroups
Is this confusing for other programmers to read my code?
should not be confusing, in fact I find it pretty informative and clear; unless you have multiple kinds of collections (lame example: suppose you have an array but also a map of SalesGroup, then SalesGroups would not be the best choice but you'd rather pick SalesGroupArray, SalesGroupMap etc.)
I think that makes perfect sense. Not specifying the type of collection means you're at liberty to change the implementation later, and clients can't rely on a particular implementation.
While it's not confusing, I think it is very easy to miss. If I were doing this, I would use something that stands out more, perhaps SalesGroup and SalesGroupCollection.
seems OK to me. just maintain your coding style throughout all your project.

Is creating an empty class purely to distinguish it from another class good practice?

I have a class CardStack. I have several classes that inherit from CardStack e.g. Cascade, Deck, Foundation etc.
Foundation doesn't need to add any functionality to CardStack, but for display purposes my app needs to know which of the CardStacks are actually Foundations.
Incidentally, I have no such function CardStack.Display() (I'm using a model-view-controller pattern where the View object simply queries the Model to find out what type of objects it's dealing with).
It seems OK to me, but is there any reason not to do this?
class Foundation : public CardStack
{
};
class Model
{
Cascade cascade[10];
Foundation foundations[10];
...
};
Nothing wrong with this.
Do it all the time.
In the future, there may be a difference in structure, behavior or implementation. For now, they happen to share a lot of common features.
I don't see any technical problem with it, so maybe you're doing this for semantic reasons. In that case, make sure you document the reason it VERY CLEARLY so maintenance programmers later on don't try and change things.
Yep, this is valid and useful. An empty class can act as placeholder for future functionality (as example). Of course, a bit of documentation is in order if the class in question is "connected" to the program in any way ;-)
In your case above, the C++ code generated won't be burdened... but readability of your code is increased.
I do it all the time for lists
public class MyObjects : List<MyObject> { }
It's good practice, since it is semantically clearer with nearly, with nearly no cost associated and allows for modifications, when the need arises for subclasses do behave differently.
Nothing wrong with it, I do this often. I like it better than empty "marker" interfaces (in Java). As others have mentioned, you should probably comment on the fact that the implementation is supposed to be empty (or perhaps "reserved for future use"), but otherwise IMHO you're fine.
The way you did it the Model class it seems to me that typedef will suffice to distinguish names (and readability!):
http://en.wikipedia.org/wiki/Typedef