How to create Haskell-like sum types in Python? - python-typing

If I have some simple sum type in Haskell, like
data Owner = Me | You
How do I express that in Python in a convenient way?

Enum or a Union is the closest thing to a tagged union or sum type in Python
Enum
from enum import Enum
class Owner(Enum):
Me = 1
You = 2
Union
https://docs.python.org/3/library/typing.html#typing.Union
import typing
class Me:
pass
class You:
pass
owner: typing.Union[Me, You] = Me

Related

SqlAlchemy query filter for Enum class property of Column(Enum(...))

I have a declarative class that has an Enum column, and the Enum has a property that returns True/False based on the specific enumerated name or value. It would simplify life if I could do a query with a filter based on this property, such as the following (see implementation below):
session.query(MyTable).filter(MyTable.letter.is_vowel)
using something like the below straightforward attempt at an expression fails with
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with MyTable.letter has an attribute 'is_vowel'
The below implementation is too simple to allow for construction of the necessary query. Is there a way to do this? I thought maybe something in a Comparator might work, or maybe there's something more sophisticated that would do it?
import enum
from sqlalchemy import (
Column,
Enum,
Integer,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
MyDeclarativeBase = declarative_base()
class Letter(enum.Enum):
A = 1
B = 2
C = 3
D = 4
E = 5
# and so on...
#property
def is_vowel(self):
return self.name in 'AEIOU'
class MyTable(MyDeclarativeBase):
__tablename__ = 'my_table'
id = Column(Integer, primary_key=True, autoincrement=True)
letter = Column(Enum(Letter), nullable=False)
#hybrid_property
def is_vowel(self):
"""Return True if the row's letter is a vowel."""
return self.letter.is_vowel
#is_vowel.expression
def is_vowel(cls):
return cls.letter.is_vowel

Choosing from a list of names using factory boy integrated with faker

I am trying to use factory.faker to randomly choose from a list of four companies and use them as a traffic source for a list of generated names. I am using the below code:
from django.db import models
import factory
import factory.django
from datetime import datetime
from django.core.validators import MinValueValidator, MaxValueValidator
from faker import Faker
from faker.providers import BaseProvider
import random
fake = Faker()
class User(models.Model):
name = models.CharField(max_length=64)
address = models.CharField(max_length=128)
phone_number = models.CharField(max_length=32)
login_date = models.DateTimeField(default=datetime.now(), blank=True)
session_duration = models.IntegerField(default = 0, validators= [
MinValueValidator(0),
MaxValueValidator(5)
])
traffic_source = models.CharField(max_length=32)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
name = factory.Faker('name')
address = factory.Faker('address')
phone_number = factory.Faker('phone_number')
login_date = factory.Faker('date')
session_duration = factory.Faker('random_int')
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
The issue is that for all 200 iterations I perform using the following in the python shell:
for _ in range(200):
UserFactory.create()
I get the same company for every name, i.e. 'XYZ' for all 200 names.
Am I missing something? I want to get a different company for each of the 200 iterations. Any help is much appreciated. Thank you!
This comes from Python's parsing rules.
Why?
When you write this:
class UserFactory(factory.django.DjangoModelFactory):
...
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
Python will execute the following steps:
Read the class declaration body;
Reach the line traffic_source = random.choice(['XYZ', 'ABC', '123', '456']);
Evaluate the call to random.choice, which might return 'ABC';
Once each line of the class body has been read (and its function calls evaluated), create the class:
UserFactory = type(
name='UserFactory',
bases=[factory.django.DjangoModelFactory],
{'traffic_source': 'ABC', ...},
)```
As you can see, the call to random.choice is performed only once, when parsing the class declaration.
This is, basically, the reason for all the factory.XXX declarations: they yield an object that will only execute its specific rules when building an instance from the factory.
So, what should you do?
Here, you should use:
Either factory.Faker using Faker's random_choices provider;
Or factory.fuzzy.FuzzyChoice:
class UserFactory(factory.django.DjangoModelFactory):
...
traffic_source = factory.Faker('random_choices', elements=['XYZ', 'ABC', '123', '456'])
alt_traffic_source = factory.fuzzy.FuzzyChoice(['XYZ', 'ABC', '123', '456'])
The main difference between factory.Faker('random_choices') and factory.fuzzy.FuzzyChoices is that factory.fuzzy.FuzzyChoices supports lazily evaluating generators; this is useful if you want to choose from a queryset:
factory.Faker('random_choices', elements=Company.objects.all()) will perform a DB query at import time;
factory.fuzzy.FuzzyChoice(Company.objects.all()) will only query the DB the first time UserFactory.create() is called.
While not truly random, the effect you're looking for when choosing from among a set of pre-existing records can also be achieved by using FactoryBoy's Iterator, which can also work with a QuerySet. For example, here I wanted every object to be created by someone different from the set of existing fake users:
from django.contrib.auth import get_user_model
...
# Then, within a factory class, for one of the fields:
created_by = factory.Iterator(get_user_model().objects.all())

How to select table name dynamically in Linq or Entity Framework

I want to call controller method for data in that there can be multiple data output from different table so it depends on user selection from which table they wanna to take output and so i was thinking to get output using single linq just by passed name of table according to user selection.
query = (from Ledger in fen.TblLedgers
join acc in fen.Accounts
on Ledger.Code equals acc.AccId
where acc.DrCr == Fin.DRCR && Ledger.Grp == Fin.LedGrp && acc.Vdate <= DateTime.Today && Ledger.isActive == "Y" group acc by new { acc.AccId } into g select g.Sum(acc => acc.Amt)).Sum() ;
If you want to do this, one approach would be to use lambdas and implement something like the below.
Long and short of it - you'd need to leverage the DbContext.Set < T > method DbContext.Set method (MSDN) or the generic one (MSDN)
Vary T (or the type parameter) by the users choice, and then lambda from there.
However, in order to do this, all T's would need to implement the same interface and you'd need to cast the elements to that interface before using them. But, you'd have to do this if you want any of this stuff to work at all...)
(Code below written freehand, don't complain if there's the odd mistake!)
So - with classes:
public interface IAnimal
{
....
}
public class Dog :IAnimal
{
....
}
public class Cat :IAnimal
{
....
}
public class Cow :IAnimal
{
...
}
You could use something like:
var userSelection = "Dog";
Type chosenType = chooseTypeAccordingToUserSelection(userSelection);
var animalDBSet = GetOpenDBcontext().Set(chosenType).Cast<IAnimal>();
var insects = animalDBSet.Where(a=>a.NumberOfLegs>4);
HTH!

Is it possible to write join with a boolean evaluation?

I want to write
CompareInfo myCompIntl = CompareInfo.GetCompareInfo( "es-ES" );
var SharedYomi = from ObjA in ClassListA
join ObjB in ClassListB
where CompareInfo.Compare(ObjA.Name, ObjB.Name) == 0
select new {stringA = stringA, string = string};
Linq forces me to write join with equals. I can not pass in a Boolean evaluation.
How can I do that?
You cannot write that using the LINQ lambda query syntax. The join keyword requires you to specify exactly two properties that are compared using the equals keyword, because this maps to the first overload of Join that uses the default comparer to compare keys.
However, there is an overload of Join that accepts an IEqualityComparer that will probably work for you, you just need to use method query syntax.
Since you sound like you're not familiar with the method syntax, here's a good starting article from MSDN:
http://msdn.microsoft.com/en-us/library/vstudio/bb397947.aspx
But, basically, the syntax you think of as "LINQ" is just one way to refer to the LINQ extensions, and is really just syntactic sugar around the IEnumerable extension methods that implement LINQ. So, for example, the query:
from x in y where x.IsActive orderby x.Name select x
it basically identical to
y.Where(x => x.IsActive).OrderBy(x => x.Name).Select(x => x);
For the most part, each query clause maps to a particular overload of a particular IEnumerable method, but those methods have a number of other overloads that take different numbers and types of parameters.
The Join methods are a bit complex, because they take two sequences as input and let you combine individual elements of them using expressions, but the idea is exactly the same. A typical join would look like this:
from x in y
join a in b on x.Id equals a.ParentId
select new { x.Id, x.Name, a.Date }
becomes
y.Join(
b,
x => x.Id,
a => a.ParentId,
(x, a) => new { x.Id, x.Name, a.Date });
This will join a.ParentId and x.Id using the default comparison for their data type (int, string, whatever). The compiler directly translates the query syntax into method syntax, so the two behave exactly the same. (Nitpicking my own answer: Technically, the methods are on the Enumerable class, so you are really calling Enumerable.Join. But as they were implemented as extension methods, you can call them either way and the compiler will figure it out.)
In your case, what you need is to pass in a different comparison method, so you can call string.Compare with the explicit encoding. The other overload of Join lets you supply an implementation of IEqualityComparer<T> to use instead of the default. This will require you to implement IEqualityComparer<string> in a separate class, since there's no easy way to create an anonymous interface implementation (perhaps the only feature I miss from Java). For your example, you want something like this:
public class ComparerWithEncoding : IEqualityComparer<string>
{
private CompareInfo compareInfo
public ComparerWithEncoding ( string encoding )
{
this.compareInfo = CompareInfo.GetCompareInfo(encoding);
}
public bool Equals ( string a, string b )
{
return CompareInfo.Compare(a, b) == 0
}
public int GetHashCode(string a)
{
return a.GetHashCode();
}
}
classListA.Join(
ClassListB,
ObjA => ObjA.Name,
ObjB => ObjB.Name,
(ObjA, ObjB) => new { stringA = ObjA.Foo, stringB = ObjB.Bar },
new ComparerWithEncoding("es-ES"));

LINQ where query on collection of different derived classes

I have a collection of different objects that derive from the same parent.
How can I extract objects of a particular type from a collection containing mixed types
e.g.
public class A {}
public class B : A {}
public class C : A {}
The collection will contain objects of type B and C
I'm halfway there just need help filling in the '[]' bit
var x = from xTypes in xCollection where '[type of object is type B]' select xTypes;
Thanks.
You should use the OfType<T> extension method rather than LINQ query syntax for this:
var x = xCollection.OfType<B>();
This will give you back an IEnumerable<B>. If you do want to use the LINQ query syntax, you'd have to do this:
var x = from obj in xCollection where obj is B select (B)obj;
var x = from xTypes in xCollection
where xTypes is B
select xTypes;
or if you want exactly this type and not any derived types:
var x = from xTypes in xCollection
where xTypes.GetType() == typeof(B)
select xTypes;

Resources