I designed my framework so it will contain devices in it (classes with metadata) and a list of interfaces (objects) in it which are responsible to connect to the specific interface on the device (using the device metadata) and execute command on it and return the output.
This interfaces usually contatins methods that is handling the output that coming from the device.
For example: executing some show command creating dataframe with the output and returning this dataframe.
Now I've encountered that this output can be different regarding to the version installed on the device.
So I want to create modules that will contain this specific methods (that aren't generic) and add them dynamically regarding the device version (Monkey patching).
For example: if the device version is 1.8.20-6 I will search for 1.8.20.py module and add it.
Now I found how to decorate those functions #some_decorater so they will be added to the interface class on run time.
In case I'm adding those modules by full path with the following code:
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
Does the python interpreter will automatically search for all decorated functions and will add them to interface class?
Or is there another way to deal with this problem? maybe some python package that deals with it.
Another question I have is why pycharm IDE isn't recognizing me modules with name x.y.z.py or x_y_z.py when I trying to import them (import framework.Versions.x_y_z)?
By the way , I know this is not a typical code problem question but more "how to" question.
It is probably a better idea to build a specific interface for each device, and use a factory to choose & return the proper object:
calling get_device_adapter with the device as argument, will return the proper DeviceAdapter object.
pseudocode:
class AbstractDeviceAdapter(ABC):
def __init__(self, ...):
initiatlize the common attributes
...
def common_method_1(self):
pass
def common_method_2(self):
do 2
#abstractmethod
def device_specific_method_0(self):
pass
#abstractmethod
def device_specific_method_1(self):
pass
class Device01Adapter(AbstractAdapterInterface):
def device_specific_method_0(self):
do specific stuff for device 01
def device_specific_method_1(self):
do specific stuff for device 01
class Device02Adapter(AbstractAdapterInterface):
def device_specific_method_0(self):
do specific stuff for device 02
def device_specific_method_1(self):
do specific stuff for device 02
def get_device_adapter(device, ...):
"""
returns the Adapter appropriate for the given device
"""
if '01' in device.__version__:
return Device01Adapter(...)
if '02' in device.__version__:
return Device02Adapter(...)
Related
Here is an image showing Python scope activity (version 3.6 and target x64):
Python Scope
The main problem is the relation between both invoke python methods, the first one is used to start the class object, and the second one to access a method of that class. Here is an image of the first invoke python properties:
Invoke Python init method
And the getNumberPlusOne activity call:
Invoke Python getNumberPlusOne method
The python code being executed:
class ExampleClass:
def __init__(self,t,n):
self.text = t
self.number = n
def getNumberPlusOne(self):
return (self.number+1)
And finally, the error when executing the second Invoke Python Method:
An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.InvalidOperationException: Error invoking Python method ----> System.Runtime.Serialization.InvalidDataContractException: Type 'UiPath.Python.PythonObject' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
Any idea about where is the mistake and how to interact with the output object created in the init method?
I believe that this activity was designed with simple scripts in mind, not with entire classes. Here's an article on their Community Forum where user Sergiu.Wittenberger goes into more details.
Let's start with the Load Python Script activity:
In my case the local variable "pyScript" is a pointer to the python object, i.e. an instance of ExampleClass.
Now, there is the Invoke Python Method activity - this one allows us to call a method by name. It seems however that methods on the class are inaccessible to UiPath - you can't just type pyScript.MethodName().
So it seems that we can't access class methods (please proof me wrong here!), but there's a workaround as shown by Sergio. In your case, you would add another method outside your class in order to access or manipulate your object:
class ExampleClass:
def __init__(self,t,n):
self.text = t
self.number = n
def getNumberPlusOne(self):
return (self.number+1)
foo = ExampleClass("bar", 42)
def get_number_plus_one():
return foo.getNumberPlusOne()
Note that this also means that the object is instantiated within the very same file: foo. At this point this seems to be the only option to interact with an object -- again, I'd hope somebody can prove me wrong.
For the sake of completeness, here's the result:
I would like to add to what the above user said that you have to make sure that the imports you use are in the global site-packages, and not in a venv as Studio doesn't have access to that.
Moreoever, always add this:
import os
import sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
to the beginning of your code. Again, a limitation of the implementation. (docs here: https://docs.uipath.com/activities/docs/load-script)
Doing this you might be able to do more complicated structures I think, but I haven't tested this out.
I use RaspberryPi3 with Python to Remote control GPIO of other RPIs.
I created a class to initialize connections and pin for all Pis:
class relay(pigpio.pi):
def __init__(self,ip_addr):
pigpio.pi.__init__(self)
self.GPIO=[4,5,6,12]
self.rpi=pigpio.pi(ip_addr)
for t in range(len(self.GPIO)):
self.rpi.write(self.GPIO[t],0)
def switch_state(self,i,state):
self.rpi.write(self.GPIO[i],state)
pi_1=relay('192.168.2.112') # creating first Rpi link
pi_2=relay('192.168.2.113') # creating second Rpi link
x=0
pi_1.switch_state(x,0)
how can I inherit pigpio module's attributes into relay ? in order not to create switch_state as I did, but to use read, write and more that belong to pigpio
If I'm right you want to extend a module to a class by inheritance.
If that is true, you can not perform that without hacky things but anyway, you should not do that.
Module and classes are not designed to be used in that way.
You better keep using module's functions as expected, I see no good reasons to map module's function within a class.
You could just map it by hand like:
import spam
class Foo():
def egg(self, *args, **kwargs):
return spam.egg(*args, **kwargs)
But again, I'm not sure there is a valid reason to do that - but there is plenty of valid reasons to not..
My code looks somewhat like this:
def write_wallet_file_entry(name, value, wallet_file, wallet_password):
some_code
some_more_code_to_write_to_the_wallet
...
I am using Python (2.6) and using unittest module for unit testing this code. Code creates the wallet file, if it does not exist and then writes a bunch of key value pairs to it.
Once I write to the wallet, there is no text parsing I can do to confirm that the write was clean.
CLARIFICATION: Stating the NOT SO obvious: I cannot use "unittest.mock" or "mock" module which would have made the problem simpler to solve. My environment is stuck on python 2.6, does not have "virtualenv", does not have "mock" module and does not allow installation of external modules on the system.
Any suggestions would be really helpful.
Some Assumptions
These assumptions won't change the gist of my answer, but they will mean we can be clear about terminology, since you haven't posted a Minimum, Complete and Verifiable Example.
A 'wallet file' is literally a file-like object. It obeys the same semantics as a file stream object, for which Python's open() is a direct wrapper.
Only the wallet_file and wallet_password are wallet file-specific. name and value are a key-value pair you seek to pass in to the file.
The Issue
Your problem here is in being able to test that your writes are 'clean'.
However, you don't need to check if the file was written to correctly or if it was created -
you'd only be testing Python's file object that way, which is pretty robustly tested already.
The point of unit tests is to test code you've written, not external services. It should always be assumed that the external service did its job in unit tests - you only test the external service in an integration test.
What you need is a way to ensure that the values you sent to be written were correctly received and not garbled, and that your request to create a file was received in the format you wanted. Test the message, not the recipient.
An Approach
One technique is to abstract your input as a class, and subclass it to have dummy methods. You can then use the subclass as a glorified mock, for all intents and purposes.
In other words, change
def write_wallet_file_entry(name, value, wallet_file, wallet_password):
...
to
class Wallet(object):
def __init__(self, wallet_file, wallet_password):
self.file = wallet_file
self.password = wallet_password
def exists(self):
# code to check if file exists in filesystem
def write(self, name, value):
# code to write name, value
def write_wallet_file_entry(name, value, WalletObject):
assert isinstance(WalletObject, Wallet), "Only Wallets allowed"
if WalletObject.exists():
WalletObject.write(name, value)
To test, you can now create MockWallet:
class MockWallet(Wallet):
def __init__(self, wallet_file, wallet_password):
super(MockWallet, self).__init__(wallet, wallet_password)
self.didCheckExists = False
self.didAttemptWrite = False
self.didReceiveCorrectly = False
def exists(self):
super(MockWallet, self).exists()
self.didCheckExists = True
def write(self, name, value):
# ... some code to validate correct arguments were pass
self.didReceiveCorrectly = True
if super(MockWallet, self).write(name, value):
self.didAttemptWrite = True
Now you can use the same function in production (just pass a Wallet!) and in tests (just pass a MockWallet and check against attributes of that object!):
import unittest
from ... import MockWallet, write_wallet_file_entry
class Test(unittest.TestCase):
def testWriteFlow(self):
mock = MockWallet()
name, value = 'random', 'more random'
write_wallet_file_entry(name, value, mock)
self.assertTrue(mock.didCheckExists)
self.assertTrue(mock.didAttemptWrite)
self.assertTrue(mock.didReceiveCorrectly)
Voila! You now have a tested write flow with a handily-improvised mock using nothing more than dependency injection instead of arbitrary function parameters.
I am working with the Python canmatrix library (well, presently my Python3 fork) which provides a set of classes for an in-memory description of CAN network messages as well as scripts for importing and exporting to and from on-disk representations (various standard CAN description file formats).
I am writing a PyQt application using the canmatrix library and would like to add some minor additional functionality to the bottom level Signal class. Note that a CanMatrix organizes it's member Frames which in turn organize it's member Signals. The whole structure is created by an import script which reads a file. I would like to retain the import script and sub-member finder functions of each layer but add an extra 'value' member to the Signal class as well as getters/setters that can trigger Qt signals (not related to the canmatrix Signal objects).
It seems that standard inheritance approaches would require me to subclass every class in the library and override every function which creates the library Signal to use mine instead. Ditto for the import functions. This just seems horribly excessive to add non-intrusive functionality to a library.
I have tried inheriting and replacing the library class with my inherited one (with and without the pass-through constructor) but the import still creates library classes, not mine. I forget if I copied this from this other answer or not, but it's the same structure as referenced there.
class Signal(QObject, canmatrix.Signal):
_my_signal = pyqtSignal(int)
def __init__(self, *args, **kwargs):
canmatrix.Signal.__init__(self, *args, **kwargs)
# TODO: what about QObject
print('boo')
def connect(self, target):
self._my_signal.connect(target)
def set_value(self, value):
self._my_value = value
self._my_signal.emit(value)
canmatrix.Signal = Signal
print('overwritten')
Is there a direct error in my attempt here?
Am I doing this all wrong and need to go find some (other) design pattern?
My next attempt involved shadowing each instance of the library class. For any instance of the library class that I want to add the functionality to I must construct one of my objects which will associate itself with the library-class object. Then, with an extra layer, I can get from either object to the other.
class Signal(QObject):
_my_signal = pyqtSignal(int)
def __init__(self, signal):
signal.signal = self
self.signal = signal
# TODO: what about QObject parameters
QObject.__init__(self)
self.value = None
def connect(self, target):
self._my_signal.connect(target)
def set_value(self, value):
self.value = value
self._my_signal.emit(value)
The extra layer is annoying (library_signal.signal.set_value() rather than library_signal.set_value()) and the mutual references seem like they may keep both objects from ever getting cleaned up.
This does run and function, but I suspect there's still a better way.
Introduction
For Java, Dependency Injection works as pure OOP, i.e. you provide an interface to be implemented and in your framework code accept an instance of a class that implements the defined interface.
Now for Python, you are able to do the same way, but I think that method was too much overhead right in case of Python. So then how would you implement it in the Pythonic way?
Use Case
Say this is the framework code:
class FrameworkClass():
def __init__(self, ...):
...
def do_the_job(self, ...):
# some stuff
# depending on some external function
The Basic Approach
The most naive (and maybe the best?) way is to require the external function to be supplied into the FrameworkClass constructor, and then be invoked from the do_the_job method.
Framework Code:
class FrameworkClass():
def __init__(self, func):
self.func = func
def do_the_job(self, ...):
# some stuff
self.func(...)
Client Code:
def my_func():
# my implementation
framework_instance = FrameworkClass(my_func)
framework_instance.do_the_job(...)
Question
The question is short. Is there any better commonly used Pythonic way to do this? Or maybe any libraries supporting such functionality?
UPDATE: Concrete Situation
Imagine I develop a micro web framework, which handles authentication using tokens. This framework needs a function to supply some ID obtained from the token and get the user corresponding to that ID.
Obviously, the framework does not know anything about users or any other application specific logic, so the client code must inject the user getter functionality into the framework to make the authentication work.
See Raymond Hettinger - Super considered super! - PyCon 2015 for an argument about how to use super and multiple inheritance instead of DI. If you don't have time to watch the whole video, jump to minute 15 (but I'd recommend watching all of it).
Here is an example of how to apply what's described in this video to your example:
Framework Code:
class TokenInterface():
def getUserFromToken(self, token):
raise NotImplementedError
class FrameworkClass(TokenInterface):
def do_the_job(self, ...):
# some stuff
self.user = super().getUserFromToken(...)
Client Code:
class SQLUserFromToken(TokenInterface):
def getUserFromToken(self, token):
# load the user from the database
return user
class ClientFrameworkClass(FrameworkClass, SQLUserFromToken):
pass
framework_instance = ClientFrameworkClass()
framework_instance.do_the_job(...)
This will work because the Python MRO will guarantee that the getUserFromToken client method is called (if super() is used). The code will have to change if you're on Python 2.x.
One added benefit here is that this will raise an exception if the client does not provide a implementation.
Of course, this is not really dependency injection, it's multiple inheritance and mixins, but it is a Pythonic way to solve your problem.
The way we do dependency injection in our project is by using the inject lib. Check out the documentation. I highly recommend using it for DI. It kinda makes no sense with just one function but starts making lots of sense when you have to manage multiple data sources etc, etc.
Following your example it could be something similar to:
# framework.py
class FrameworkClass():
def __init__(self, func):
self.func = func
def do_the_job(self):
# some stuff
self.func()
Your custom function:
# my_stuff.py
def my_func():
print('aww yiss')
Somewhere in the application you want to create a bootstrap file that keeps track of all the defined dependencies:
# bootstrap.py
import inject
from .my_stuff import my_func
def configure_injection(binder):
binder.bind(FrameworkClass, FrameworkClass(my_func))
inject.configure(configure_injection)
And then you could consume the code this way:
# some_module.py (has to be loaded with bootstrap.py already loaded somewhere in your app)
import inject
from .framework import FrameworkClass
framework_instance = inject.instance(FrameworkClass)
framework_instance.do_the_job()
I'm afraid this is as pythonic as it can get (the module has some python sweetness like decorators to inject by parameter etc - check the docs), as python does not have fancy stuff like interfaces or type hinting.
So to answer your question directly would be very hard. I think the true question is: does python have some native support for DI? And the answer is, sadly: no.
Some time ago I wrote dependency injection microframework with a ambition to make it Pythonic - Dependency Injector. That's how your code can look like in case of its usage:
"""Example of dependency injection in Python."""
import logging
import sqlite3
import boto.s3.connection
import example.main
import example.services
import dependency_injector.containers as containers
import dependency_injector.providers as providers
class Platform(containers.DeclarativeContainer):
"""IoC container of platform service providers."""
logger = providers.Singleton(logging.Logger, name='example')
database = providers.Singleton(sqlite3.connect, ':memory:')
s3 = providers.Singleton(boto.s3.connection.S3Connection,
aws_access_key_id='KEY',
aws_secret_access_key='SECRET')
class Services(containers.DeclarativeContainer):
"""IoC container of business service providers."""
users = providers.Factory(example.services.UsersService,
logger=Platform.logger,
db=Platform.database)
auth = providers.Factory(example.services.AuthService,
logger=Platform.logger,
db=Platform.database,
token_ttl=3600)
photos = providers.Factory(example.services.PhotosService,
logger=Platform.logger,
db=Platform.database,
s3=Platform.s3)
class Application(containers.DeclarativeContainer):
"""IoC container of application component providers."""
main = providers.Callable(example.main.main,
users_service=Services.users,
auth_service=Services.auth,
photos_service=Services.photos)
Here is a link to more extensive description of this example - http://python-dependency-injector.ets-labs.org/examples/services_miniapp.html
Hope it can help a bit. For more information please visit:
GitHub https://github.com/ets-labs/python-dependency-injector
Docs http://python-dependency-injector.ets-labs.org/
Dependency injection is a simple technique that Python supports directly. No additional libraries are required. Using type hints can improve clarity and readability.
Framework Code:
class UserStore():
"""
The base class for accessing a user's information.
The client must extend this class and implement its methods.
"""
def get_name(self, token):
raise NotImplementedError
class WebFramework():
def __init__(self, user_store: UserStore):
self.user_store = user_store
def greet_user(self, token):
user_name = self.user_store.get_name(token)
print(f'Good day to you, {user_name}!')
Client Code:
class AlwaysMaryUser(UserStore):
def get_name(self, token):
return 'Mary'
class SQLUserStore(UserStore):
def __init__(self, db_params):
self.db_params = db_params
def get_name(self, token):
# TODO: Implement the database lookup
raise NotImplementedError
client = WebFramework(AlwaysMaryUser())
client.greet_user('user_token')
The UserStore class and type hinting are not required for implementing dependency injection. Their primary purpose is to provide guidance to the client developer. If you remove the UserStore class and all references to it, the code still works.
After playing around with some of the DI frameworks in python, I've found they have felt a bit clunky to use when comparing how simple it is in other realms such as with .NET Core. This is mostly due to the joining via things like decorators that clutter the code and make it hard to simply add it into or remove it from a project, or joining based on variable names.
I've recently been working on a dependency injection framework that instead uses typing annotations to do the injection called Simple-Injection. Below is a simple example
from simple_injection import ServiceCollection
class Dependency:
def hello(self):
print("Hello from Dependency!")
class Service:
def __init__(self, dependency: Dependency):
self._dependency = dependency
def hello(self):
self._dependency.hello()
collection = ServiceCollection()
collection.add_transient(Dependency)
collection.add_transient(Service)
collection.resolve(Service).hello()
# Outputs: Hello from Dependency!
This library supports service lifetimes and binding services to implementations.
One of the goals of this library is that it is also easy to add it to an existing application and see how you like it before committing to it as all it requires is your application to have appropriate typings, and then you build the dependency graph at the entry point and run it.
Hope this helps. For more information, please see
github: https://github.com/BradLewis/simple-injection
docs: https://simple-injection.readthedocs.io/en/latest/
pypi: https://pypi.org/project/simple-injection/
A very easy and Pythonic way to do dependency injection is importlib.
You could define a small utility function
def inject_method_from_module(modulename, methodname):
"""
injects dynamically a method in a module
"""
mod = importlib.import_module(modulename)
return getattr(mod, methodname, None)
And then you can use it:
myfunction = inject_method_from_module("mypackage.mymodule", "myfunction")
myfunction("a")
In mypackage/mymodule.py you define myfunction
def myfunction(s):
print("myfunction in mypackage.mymodule called with parameter:", s)
You could of course also use a class MyClass iso. the function myfunction. If you define the values of methodname in a settings.py file you can load different versions of the methodname depending on the value of the settings file. Django is using such a scheme to define its database connection.
I think that DI and possibly AOP are not generally considered Pythonic because of typical Python developers preferences, rather that language features.
As a matter of fact you can implement a basic DI framework in <100 lines, using metaclasses and class decorators.
For a less invasive solution, these constructs can be used to plug-in custom implementations into a generic framework.
There is also Pinject, an open source python dependency injector by Google.
Here is an example
>>> class OuterClass(object):
... def __init__(self, inner_class):
... self.inner_class = inner_class
...
>>> class InnerClass(object):
... def __init__(self):
... self.forty_two = 42
...
>>> obj_graph = pinject.new_object_graph()
>>> outer_class = obj_graph.provide(OuterClass)
>>> print outer_class.inner_class.forty_two
42
And here is the source code
Due to Python OOP implementation, IoC and dependency injection are not standard practices in the Python world. But the approach seems promising even for Python.
To use dependencies as arguments is a non-pythonic approach. Python is an OOP language with beautiful and elegant OOP model, that provides more straightforward ways to maintain dependencies.
To define classes full of abstract methods just to imitate interface type is weird too.
Huge wrapper-on-wrapper workarounds create code overhead.
I also don't like to use libraries when all I need is a small pattern.
So my solution is:
# Framework internal
def MetaIoC(name, bases, namespace):
cls = type("IoC{}".format(name), tuple(), namespace)
return type(name, bases + (cls,), {})
# Entities level
class Entity:
def _lower_level_meth(self):
raise NotImplementedError
#property
def entity_prop(self):
return super(Entity, self)._lower_level_meth()
# Adapters level
class ImplementedEntity(Entity, metaclass=MetaIoC):
__private = 'private attribute value'
def __init__(self, pub_attr):
self.pub_attr = pub_attr
def _lower_level_meth(self):
print('{}\n{}'.format(self.pub_attr, self.__private))
# Infrastructure level
if __name__ == '__main__':
ENTITY = ImplementedEntity('public attribute value')
ENTITY.entity_prop
EDIT:
Be careful with the pattern. I used it in a real project and it showed itself a not that good way. My post on Medium about my experience with the pattern.