Страницы

Поиск по вопросам

пятница, 28 февраля 2020 г.

Папки с дополнительными NuGet пакетами для .net Core

#visual_studio_2017 #net_core #nuget


Исходные данные: ПК без доступа к интернету, VS2017 и проект на .net Core.
На ПК есть общая "офлайн папка с пакетами", откуда черпаются все основные (например
%userprofile%\.nuget\packages\).
Вопрос: Можно ли проекту указать дополнительную папку, в которой бы брались пакеты,
которые не были найдены в общей папке? Только для этого проекта.
    


Ответы

Ответ 1



Папка %userprofile%\.nuget\packages\ представляет из себя Local Feeds - папка с иерархичной структурой хранения nuget-пакетов, из которой можно устанавливать nuget-пакеты. Для того, чтобы подключить дополнительный Local Feeds в проект, вы можете сделать: На уровне папки проекта создайте файл NuGet.Config. В этом файле прописать следующее содержимое Элемент packageSources содержит список источников для установки пакетов. Если вы используете NetCore2.0, тогда путь до источника nuget-пакетов можно указать прямо в файле проекта(csproj) следующим образом $(RestoreSources);c:\packages; https://api.nuget.org/v3/index.json

Ответ 2



Может то, а может не совсем, но тем не менее. Из [Spec] Fallback package folders: Fallback package folders allow packages to be shared across users and machines to reduce disk space. These folders are treated as fallback folders for the primary global packages folder (%USERPROFILE%.nuget\packages). They differ from package sources in that the package assets will be referenced directly and will not be copied into the user's packages folder. The concept of a fallback package folder can be thought of as a GAC for nupkgs. [Spec] NuGet settings in MSBuild Свойство RestoreFallbackFolders - Fallback folders, these are used in the same way the user packages folder is used. Свойство RestoreAdditionalProjectFallbackFolders - Additional fallback folders appended to the resulting list of fallback folders Имеется пакет NLog в global packages folder. Если запустить сборку проекта, то в логах будет видно, что пакет подгружается из упомянутой директории: 1> Primary reference "NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c". 1> Resolved file path is "C:\Users\username\.nuget\packages\nlog\4.5.7\lib\netstandard2.0\NLog.dll". 1> Reference found at search path location "{HintPathFromItem}". 1> This reference is not "CopyLocal" because at least one source item had "Private" set to "false" and no source items had "Private" set to "true". 1> The ImageRuntimeVersion for this reference is "v4.0.30319". Добавим в проект с помощью свойства RestoreAdditionalProjectFallbackFolders резервный источник: C:\Users\username\Desktop\Username Удаляем NLog из global packages folder (в искомой "офлайн папке" пакета не оказалось) и запускаем сборку проекта: 1> Primary reference "NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c". 1> Resolved file path is "C:\Users\username\Desktop\Username\nlog\4.5.7\lib\netstandard2.0\NLog.dll". 1> Reference found at search path location "{HintPathFromItem}". 1> This reference is not "CopyLocal" because at least one source item had "Private" set to "false" and no source items had "Private" set to "true". 1> The ImageRuntimeVersion for this reference is "v4.0.30319". В рамках restore операции пакет подгружается из FallbackFolder если оный отсутствует в global packages folder, и не копируется в него по окончанию. Даже при наличии доступа к сети, пакет берется из FallbackFolder. UPD: В случае использования packageSources не до конца понятна ситуация с приоритетностью источников, ибо тут сказано, что: All feeds are queried and the one with the shortest response time wins. Кроме того, пакеты из локального источника будут копироваться в global packages folder, т.е дублироваться.

Настройка отображения элементов в RecyclerView через GridLayoutManager в строке

#android


Необходимо настроить recyclerView таким образом, чтобы расположение элементов  в
каждой второй строке было по 2, а в нечётных строках по одному item'у.

Как сделать по два элемента во всех строках, т.е. 2 колонки, - это понятно:

GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(layoutManager);


а вот как сделать чередование - в одной два, а в другой один item?
Я подозреваю, что это какой-то метод GridLayoutManager'a, но как и где его применять?
В onCreateViewHolder'е?

Спасибо!
    


Ответы

Ответ 1



Попробуй так: GridLayoutManager layoutManager = new GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false); layoutManager.setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if((position % 3) == 0){ return 2; } else return 1; } }); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(adapter);

Как сделать, чтобы моя функция set_checkpoints() корректно обрабатывала текстовый файл

#python #python_3x


У меня есть текстовый файл data.txt:

яблоко
банан
абрикос
яблоко
апельсин
апельсин
мандарин 
абрикос
абрикос
абрикос
абрикос
абрикос


Я пытаюсь сделать так, чтобы после обработки файла data.txt  функцией set_checkpoints()
на выходе получался файл save.txt:

//А//яблоко//А//   
//А//банан//А// 
//А//абрикос//А//
//А//яблоко//А//
//А//апельсин//А//
//А//апельсин//А// 
//А//мандарин//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//


Но в результате у меня получается вот что:

//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
яблоко
//А//апельсин//А//
апельсин
//А//мандарин//А// 
абрикос
абрикос
абрикос
абрикос
абрикос


Решение:
Нужно сделать так, чтобы функция при нахождении нужного слова из массива, продолжил
поиск данного слова до конца файла, а не прерывался на первом же совпадении и переходил
бы к следующему слову. В итоге у меня получается, что он находит из массива fruits
совпадение со словом из текстового файла, отмечает его чекпойтами и переходит к поиску
следующего слова из массива. Как сделать так, чтобы функция работала корректно? 

Вот мой код: 

import re

path = 'data.txt' # input data
save = 'save.txt' # output data

def open_read(path): # функция открывает и считывает файл
    file = open(path, 'r')
    content = file.read()
    file.close()
    #print(content)
    return content


Fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов

n=len(Fruits) # определение размера массива Fruits

def set_checkpoints(content): # функция устанавливает checkpoints
    for i in range(n):
        find = re.compile(Fruits[i])
        res = find.search(content)
        #lenght = len(find.findall(content)) # определяет общее количество конкретного
найденного слова
        #print (lenght)
        #for i in range(lenght):
        if res == None: continue #  Если не обнаружено слово
        else:
            k1 = res.start()
            k2 = res.end()
            content = content[:k1]+"//А//"+content[k1:k2]+"//А//"+content[k2:]
    print(content)
    return content
###############################################

content = open_read(path) # окрываем файл
content = set_checkpoints(content) # обрабатываем файл функцией set_checkpoints()

file = open(save, 'w') # сохраняем файл
file.write(content)
file.close()


P.S.
Я так понимаю тут дело заключается в методе search(), т.к. метод search() ищет по
всей строке, но возвращает только первое найденное совпадение. Тут похоже нужно использовать
метод findall(), т.к. этот метод возвращает список всех найденных совпадений. Но я
не знаю, как в findall() реализовать установку чекпоинтов. Свойства start() и end()
работают только в методе search(). 

Помогите, пожалуйста.
    


Ответы

Ответ 1



Не нужны тут регулярные выражения: fruits = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин'] with open('input.txt', encoding='utf-8') as f_in: with open('output.txt', 'w', encoding='utf-8') as f_out: for line in f_in: # Для удаления справа пустых символов: ' ', '\n', '\r', и т.п. line = line.rstrip() # Если фрукт есть в списке if line in fruits: f_out.write('//А//{}//А//\n'.format(line)) Если работать с текстом и через функцию: FRUITS = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин'] def set_checkpoints(text: str) -> str: # В одну строку return '\n'.join( '//А//{}//А//'.format(line) for line in text.splitlines() if line in FRUITS ) # NOTE: тот же код, что выше # new_lines = [] # # for line in text.splitlines(): # if line in FRUITS: # new_lines.append('//А//{}//А//'.format(line)) # # return '\n'.join(new_lines) with open('input.txt', encoding='utf-8') as f: content = f.read() # Обрабатываем файл функцией set_checkpoints() content = set_checkpoints(content) with open('output.txt', 'w', encoding='utf-8') as f: f.write(content) Результат (output.txt): //А//яблоко//А// //А//банан//А// //А//абрикос//А// //А//яблоко//А// //А//апельсин//А// //А//апельсин//А// //А//мандарин//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А//

Ответ 2



Если планируется обрабатывать небольшие файлы (заведомо меньшие половины свободной оперативной памяти), то можно заменять текст без циклов: import re from pathlib import Path fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов pref, suff = '//А//', '//А//' text = Path(r'D:\temp\1.txt').read_text(encoding='utf-8') pat = r'(\b)({})(\b)'.format('|'.join(fruits)) text = re.sub(pat, r'\1{}\2{}\3'.format(pref, suff), text) Path(r'D:\temp\result.txt').write_text(text, encoding='utf-8') # check print(Path(r'D:\temp\result.txt').read_text(encoding='utf-8')) результат: //А//яблоко//А// //А//банан//А// //А//абрикос//А// //А//яблоко//А// //А//апельсин//А// //А//апельсин//А// //А//мандарин//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А//

Скрыть консоль без использования FreeConsole()

#cpp #windows #консоль


Есть ли возможность как-то по другому скрыть консоль?
    


Ответы

Ответ 1



Ну для начала вы можете и не создавать консоль используя только функцию winmain В случае если у вас Visual Studio, в настройках линковки Project->Properties->Linker->System->Subsystem указываете подсистему Windows (/SUBSYSTEM:WINDOWS). Консоль исчезла, а нагрузка будет минимальная.

Ответ 2



Если нужно временно скрыть или отобразить консоль, можно использовать следующие функции: #include void HideConsole() { ::ShowWindow(::GetConsoleWindow(), SW_HIDE); } void ShowConsole() { ::ShowWindow(::GetConsoleWindow(), SW_SHOW); } Источник: C++ How do I hide a console window on startup? - ответ nikau6

Почему рецепт unique_justseen() из Itertools Recipes так сложно реализован?

#python #python_3x #iterator


В документации Питона в разделе 10.1.2. Itertools Recipes находится такой рецепт:


def unique_justseen(iterable, key=None):
    "List unique elements, preserving order. Remember only the element just seen."
    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
    # unique_justseen('ABBCcAD', str.lower) --> A B C A D
    return map(next, map(operator.itemgetter(1), itertools.groupby(iterable, key)))



По моему это напрасно сложное, так как команду return возможно написать так:

     return map(operator.itemgetter(0), itertools.groupby(iterable, key))


Это прекрасно работает, но может быть, что я что-то не заметил а существует такой
пример iterable, с которым "официальная" версия работает правильно, но моя нет.

Знаете такой случай, или мой подход кажется правильным?
    


Ответы

Ответ 1



Вариант map(operator.itemgetter(0), itertools.groupby(iterable, key)) не является верным, так как вы вернете значения ключа полученное при использовании функции key. То есть при выполнении map(operator.itemgetter(0), itertools.groupby('AabBCC', str.lower)) вы получите результат ['a', 'b', 'c'] соответствующий ключам, но не первому встреченному элементу. Выполняя map(next, map(operator.itemgetter(1), itertools.groupby('AabBCC', str.lower))) получим ['A', 'b', 'C'] что соответствует первому встреченному элементу группы.

Почему findFragmentById возвращает null?

#java #android #android_studio


Объясните пожалуйста, почему getSupportFragmentManager().findFragmentById(R.id.fragment_container)
возвращает null если в классе  SingleFragmentActivity он добавляется в FragmentManager?

 


.

public class MyFragment extends Fragment {
}


.

public abstract class SingleFragmentActivity extends AppCompatActivity {
    FragmentManager fm= getSupportFragmentManager();
    protected abstract Fragment createFragment();
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_fragment);
           Fragment fragment = fm.findFragmentById(R.id.fragment_container);
           if (fragment == null) {
               fragment = createFragment();
               fm.beginTransaction()
                       .add(R.id.fragment_container, fragment)
                       .commit();
           }
       }
}


.

public class MyActivity extends SingleFragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Возвращает null
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    }
    @Override
    protected Fragment createFragment() {
        return new MyFragment();
    }
}

    


Ответы

Ответ 1



Вызов commit() не выполняет транзакцию немедленно, а ставит в очередь UI-потока. Поэтому следующий за ним вызов findFragmentById выполняется раньше, чем фрагмент будет добавлен. Вместо этого можно завершить транзакцию синхронным методом commitNow() - тогда всё выполнится по порядку.

Ответ 2



Вот так вот у меня находит фрагмент

Можно ли над методом рест-контроллера ставить аннотацию @Transactional?

#java #spring #транзакции #jta


Можно ли над методом рест-контроллера ставить аннотацию @Transactional?
Будут ли проблемы, если одновременно по этому URL одновременно будут пытаться получить
данные несколько клиентов?
    


Ответы

Ответ 1



Нельзя, однозначно и бесповоротно. Будут проблемы связанные с обработкой транзакций. Здесь я укажу некоторые ссылки: Слой использования @Transactional анотации.. Что лучше всего с @Transactional, вы должны положить его, если у вас есть доступ к базе данных. См. «Понимание реализации декларативной транзакции Spring Framework» вы просто аннотируете свои классы аннотацией @Transactional, добавляете в свою конфигурацию строку (``), а затем ожидаете, что вы поймете, как все это работает. Какой слой использовать для транзакций и сессии Hibernate. Лучше всего использовать управление транзакциями Spring. Аннотации @Transactional для использования транзакций. На заводе-изготовителе используется LocalSessionFactoryBean. Все бобы управляются весной, поэтому у вас нет забот. Spring Hibernate - различие между CrudRepository и SessionFactory. Просто вы можете найти описание этих аннотаций на сайте docs Spring. В ближайшее время, чтобы ответить на ваши вопросы, разница между ними заключается в том, что они используются для разных целей. @Transactional используется для демаркации кода, участвующего в транзакции. Он помещается на классы и методы. @Repository используется для определения Spring-компонента, поддерживающего транзакции, его также можно использовать в DI. Они могут использоваться как в одном классе.

Ответ 2



Можно. Никаких технических ограничений для этого нет. Но не нужно, так как это неправильно с точки зрения проектирования архитектуры. Ни контроллеры, ни слой доступа к данным не могут располагать необходимыми знаниями о взаимосвязях данных, в контексте которых имеет смысл транзакции применять. Это прерогатива сервисного слоя, в котором и должна располагаться вся бизнес-логика. UPDATE: Так как правильность моего ответа ставят под сомнение, придётся его дополнить. Во-первых, мне приходилось видеть проекты крупных и солидных компаний, в которых на протяжении многих лет транзакции успешно используется именно в web-слое. Во-вторых, первая же ссылка в Google по запросу "spring @transactional @controller" ведёт на большой SO, где люди делятся тем же опытом. Наконец, не может быть более железного аргумента, чем рабочий код. Поэтому я накидал простенький проект и залил его на GitHub - https://github.com/TheDeadOne/spring-transactional-controller-demo.

Ответ 3



Можно Пост процессор, увидев аннотацию @Transactional вокруг аннотированного класса создаст прокси, в котором будут происходить (очень примерно) две вещи Выполняться beginTransaction() перед аннотированным методом (или перед каждым публичным методом аннотированного класса) Выполняться .getTransaction().commit() после аннотированного метода (или после каждого публичного метода аннотированного класса) С точки зрения многопоточности от заворачивания контроллера в прокси ничего не меняется. Но не нужно А вот с точки зрения архитектуры это плохая идея. Первая буква в слове SOLID: The Single Responsibility Principle Ответственность контроллера - получить request и попросить кого нибудь его обработать и отправить ответ. Не надо вешать на него дополнительную функциональность.