Is there a way with traits to get all imported modules or some other way? As far as I can see "allMembers" will not include members imported.
What I want to achieve is to import all members from within imported modules, but it doesn't seem to be as easy as I thought. I can easily get the members I want if I specify the full modules imported, but not if I take the current module itself.
So my question is, is there a way in D to get the names of all modules that are imported, because that way I can create a dynamic way of using "allMembers" on the modules.
To demonstrate what I mean.
Let's say we have module a.
module a;
import b;
import c;
...
foreach (member; __traits(allMembers, a)) {
// members of b and c will not come here ...
}
Even if the imports of b and c are public, then they won't come.
What I want to be able to do is retrieve them there anyway.
If you import into a structure, then allMembers should work work; example:
( https://dpaste.dzfl.pl/629ff05bdab0 )
struct Packages {
import std_meta = std.meta;
import std_range = std.range;
import std_range_interfaces = std.range.interfaces;
import std_range_primitives = std.range.primitives;
import std_traits = std.traits;
};
void main() {
foreach (X; __traits(allMembers, Packages)) {
pragma(msg, __traits(allMembers, __traits(getMember, Packages, X)));
};
};
… with some caveats which I don't recall exactly right now.
If you also want the modules to be imported 'normally' you could generate string-mixins from a list of module names. There's probably a number of ways you could approach this. (I won't go into details unless someone specifically asks about it)
I used this technique to great effect in my std-underscore hack, with some help from __traits(compiles and __traits(getProtection. So you might want to check that out if you plan on doing something similar.
It's actually not as flimsy as you'd expect. I use std-underscore in every project now.
Related
Scenario
Imagine that you have a module X whose functionalities are available to the user through a Command Line Interface. Such module doesn't do much in and of itself but it allows for other people to create plugin-like modules they can hook-up to module X. Ideally, the plugins could be used through X's CLI.
Thus my question:
What do you need to do in order to hook-up whatever functionality
a plugin might provide to X's CLI?
This means the plugin would need to provide some structure describing the command, what needs to be called and hopefully a usage message for the plugin. Therefore, when you run X's CLI, the plugin's command and help message shows up in the regular X's CLI's help message.
Example
main.p6:
use Hello;
use Print;
multi MAIN('goodbye') {
put 'goodbye'
}
lib/Hello.pm6:
unit module Hello;
our %command = %(
command => 'hello',
routine => sub { return "Hello" },
help => 'print hello.'
);
lib/Print.pm6:
unit module Print;
our %command = %(
command => 'print',
routine => sub { .print for 1..10 },
help => 'print numbers 1 through 10.'
);
The program main.p6 is a simplified version of this scenario. I'd like to integrate the information provided by both Hello.pm6 and Print.pm6 through
their respective %command variables into two new MAIN subs in main.p6.
Is this possible? If so, how would I go about achieving it?
This looks kinda specific for a StackOverflow question, but I will give it a try anyway. There are a couple of issues here. First one is to register the commands as such, so that MAIN can issue a message saying "this does that", and second is to actually perform the command. If both can be known at compile time, this can probably be fixed. But let's see how the actual code would go. I'll just do the first part, and I leave the rest as an exercise.
The first thing is that %command needs somehow to be exported. You can't do it the way you are doing it now. First, because it's not explicitly exported; if it were, you would end up with several symbols with the same name in the outer scope. So we need to change that to a class, so that the actual symbols are lexical to the class, and don't pollute the outer scope.
unit class Hello;
has %.command = %(
command => 'hello',
routine => sub { return "Hello" },
help => 'print hello.'
);
(Same would go for Print)
As long as we have that, the rest is not so difficult, only we have to use introspection to know what's actually there, as a small hack:
use Hello;
use Print;
my #packages= MY::.keys.grep( /^^<upper> <lower>/ );
my #commands = do for #packages -> $p {
my $foo = ::($p).new();
$foo.command()<command>
};
multi MAIN( $command where * eq any(#commands) ) {
say "We're doing $command";
}
We check the symbol table looking for packages that start with a capital letter, followed by other non-capital letter. It so happens that the only packages are the ones we're interested in, but of course, if you would want to use this as a plugin mechanism you should just use whatever pattern would be unique to them.
We then create instances of these new packages, and call the command auto-generated method to get the name of the command. And that's precisely what we use to check if we're doing the correct command in the MAIN subroutine, by using the where signature to check if the string we're using is actually in the list of known commands.
Since the functions and the rest of the things are available also from #packages, actually calling them (or giving an additional message or whatever) is left as an exercise.
Update: you might want to check out this other StackOveflow answer as an alternative mechanism for signatures in modules.
I'm looking for some cleanup of my knowledge. Within a project with complex module structure I'd like to keep the structure clean by building up structured namespace tree. Say, something like:
App
Config
Key
Node
Param
Type
MyType
Every entry under App::Config shall be contained in its own file. Always typing things like App::Config::Key is a time waste. is export doesn't have a parameter to declare the name which is to be exported. So, I finally came to the following solution:
Config.pm6:
unit module App::Config:ver<0.0.1>;
...
Key.pm6:
unit package App::Config;
class Key is export {
...
}
And it works as I want it:
use App::Config::Key;
say Key.^name; # App::Config::Key
The only question remains: a there any caveats? Any hidden side effects to know about?
Far as I can tell, the only problem seems to be you will only be able to recursively declare modules that way. Only one, at the top level, will be possible. See this (simplified) example:
lib/Packr/U/Packd.rakumod:
unit package Packr::U;
our class Pack'd is export {}
lib/Packr/U.rakumod:
unit module Packr::U;
lib/Packr/Packd.rakumod:
unit package Packr;
our class Pack'd is export {}
our class B::Pack'd is export {}
lib/Packr.rakumod:
unit module Packr::U;
And then the main program:
use Packr;
use Packr::U;
for (Packr::Pack'd Packr::B::Pack'd Packr::U::Pack'd ) -> \P {
say P.new().raku;
}
This fails in the last iterated class:
Could not find symbol '&Pack'd' in 'Packr::U'
I have a problem in code design. I try to read some files and create for every file one or more instances (dependin on the content). But some instances depend on other files in the list, so that every instance has to know the top class. Following example should illustrate what I mean:
class SetOfAll(object)
def __init__(self):
self.matrjoschkas = []
def add(self, matrjoschka):
self.matrjoschkas.append(matrjoschka)
def create_matrjoschkas(self):
for file in glob.glob('*.txt'):
self.add(Matrjoschka(file, self))
class Matrjoschka(object)
def __init__(self, file, container):
self._container = container
...
if some condition:
self._container.add(Matrjoschka(..., self._container))
Is there an elegant way to avoid, that every instance has to know the top class? Because in my case it's a little bit more complicated and it would be good if some factory could do it.
Well, there are certainly many ways of doing this, but from what I can see you just need a way to explicitly state the dependencies between files. You could then ask a factory to create a list of files based on the file's source and the configured dependencies.
Pseudo-code:
filesFactory = new FilesFactory({
file1: ['file2', 'file3'] //file1 depends on file2 and file3
});
filesSource = new GlobFilesSource('*.txt'); //FilesSource could be an abstraction and GlobFilesSource a concrete implementation
allFiles = filesFactory.resolveAllFilesFrom(filesSource); // ['file1', 'file2', 'file3']
If the dependency conditions are more complex than a simple id matching then you could just configure predicates. Here's a pseudo-code sample using a predicate to achieve the same dependency configuration as above:
[
{
predicate: function (currentFiles) {
return currentFiles.contains('file1');
},
files: ['file2', 'file3']
}
]
This design is much more flexible than yours because not only the Matrjoschka class doesn't have to know about it's container, but it also doesn't have to know about dependency rules.
I'm trying to make a extbase extension for TYPO3 to get alle file objects with mimetype image/... which referenced by any content, plugin or fluid in typo3.
But i don't know which is the best way to get these data. How should i create a model in my extension and how should i create the correct repository?
If i create a custom query i'm not sure how to return a complete FAL Object which contains any data (like metadata) etc.
hope someone could help me to find the right way, and maybe has a example or something.
thanks a lot
You could do it like this, details are at the bottom:
Get all file references.
Go through them, retrieve the referenced file for each of them and retain only the ones where the field mime_type starts with image/.
There are two things you probably need to watch out for:
The field mime_type needs to be up to date. Check the FAL scheduler indexing task for that.
Performance. Depending on the number of files you have, it could be much faster to do this with a custom SQL statement which makes use of a JOIN. But you should only do that if performance is a problem.
How to get all file references:
First, build your own empty file reference class:
namespace Vendor/Extkey/Domain/Model;
class FileReference extends \TYPO3\CMS\Extbase\Domain\Model\FileReference {}
Make sure to configure it in your TypoScript to be serialized to the table sys_file_reference:
config.tx_extbase.persistence {
classes {
Vendor\Extkey\Domain\Model\FileReference {
mapping {
tableName = sys_file_reference
}
}
}
}
Add a repository for the references:
namespace Vendor/Extkey/Domain/Repository;
class FileReferenceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
public function initializeObject() {
/** #var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface */
$defaultQuerySettings = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QuerySettingsInterface');
$defaultQuerySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($defaultQuerySettings);
}
}
The reference class can be empty, but the repository needs it to be there in order to work correctly. Make sure you add the default query settings to ignore the page id, so you get all non-hidden and non-deleted file references by calling $fileReferenceRepository->findAll().
How to check the MIME-type of each referenced file:
You can get the MIME-type of each reference by calling
$fileReference->getOriginalResource()->getMimeType()
This should automatically fetch the original file from storage and read its MIME-type.
Given this somewhat simplified representation of my application's models, my question is how do I globally find the most popular MyModel? I.e., those MyModels are favorited the most by MyUsers.
I've come across similar blog posts about how to find favorite tags, but I don't think those apply to this particular situation.
class MyUser(models.Model):
favorite_models = models.ManyToManyField(MyModel)
...
class MyModel(models.Model):
name = models.CharField(...)
...
Can this be done in a single query? Or do I need to loop over every MyUser and MyModel to determine the most popular? Thanks in advance!
I'm too lazy to create a django project from scratch, but this one should do the job:
from django.db.models import Count
MyModel.objects.annotate(Count('myuser'))
(or this)
MyModel.objects.annotate(Count('myuser_set'))
if not, try this:
class MyUser(models.Model):
favorite_models = models.ManyToManyField(MyModel, related_name='myuser')
and then
MyModel.objects.annotate(Count('myuser_set'))
(let me know if it works, in any case this page should contain what you need to do that: https://docs.djangoproject.com/en/dev/topics/db/aggregation/)